Skip to content

Instantly share code, notes, and snippets.

@kflorence
Last active September 1, 2022 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kflorence/a545757d0b6e9f6f9ca3295c8f30e798 to your computer and use it in GitHub Desktop.
Save kflorence/a545757d0b6e9f6f9ca3295c8f30e798 to your computer and use it in GitHub Desktop.
An IRC daemon written in PHP
<?
#require("server-functions.php");
#Phircd v 0.1.0 - written by siron.
set_time_limit(0);
error_reporting(0);
/* reads the config file and defines commands
$cline = file("ircd.conf") or die("cannot find ircd.conf!");
$cnum_lines = count($cline);
$conf = 0;
while ($conf < $cnum_lines) {
if (substr($cline[$conf],0,1) == ":") {
$this = explode(" ", $cline[$conf]);
$command = str_replace(":", "", $this[0]);
$information = str_replace("\"", "", $this[2]);
define($command, $information);
}
$conf++;
}
*/
define('SERVERNAME', 'ircd.waxoff.net');
define('PORT', 6667);
define('BIND_IP', '0.0.0.0');
define('LISTENQ', 10);
define('CLIENT_MAX', 10);
define('NETWORK', 'Phircd');
define('MAXLINE', 1024);
define('NICKLEN', 15);
define('VERSION', 'Phircd-1.0beta1');
define('MODES', 'i'); // server modes
$user_current = 0;
$user_top = 0;
$user_invis = 0;
$connection_count = 0;
/************************************************************
Listening, socket options, and binding.
************************************************************/
// listening
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
if ($socket)
{
print SERVERNAME . " Listening on port " . PORT . "\n";
}
else
{
die("Sock_Error: socket has closed.\n");
}
socket_setopt($socket, SOL_SOCKET, SO_REUSEADDR, 1);
if (!socket_bind($socket, BIND_IP, PORT))
{
socket_close($socket);
die("Sock_Error: Socket was unable to bind.\n");
}
socket_listen($socket, LISTENQ);
/*************************************************************
Various functions for data handling.
*************************************************************/
// introduces new client
function new_client($this_client)
{
global $socket, $c_data, $i, $motd, $maxi, $client, $remote_host, $remote_port;
#$c_data[$client[$i]]['throttle'] = time();
$client[$i] = $this_client;
$client[$i] = socket_accept($socket);
socket_setopt($client[$i], SOL_SOCKET, SO_REUSEADDR, 1);
socket_getpeername($client[$i], $remote_host[$i], $remote_port[$i]);
/*
for ($c = 0; $c < $maxi; $c++)
{
if ($c_data[$client[$c]]['host'] == $remote_host[$i]) {
if ((time()-$c_data[$client[$c]]['throttle']) < 10) {
send_quit($client[$i],null,"Throttle control: Trying to connect too fast!\r\n");
break;
}
}
if ($done) break;
}
$clones = 1;
for ($c = 0; $c < $maxi; $c++)
{
if ($c_data[$client[$c]]['host'] == $remote_host[$i]) {
$clones++;
}
if ($clones > 2) {
send_quit($client[$i],null,"Too many connections from your host\r\n");
$done = 1;
break;
}
if ($done) break;
}
*/
socket_write($client[$i], ":" . SERVERNAME . " NOTICE AUTH :*** Looking up your hostname...\r\n");
// get the users information
$data = trim(socket_read($client[$i], MAXLINE));
$data = explode(" ", $data);
if ($data[0] == "NICK")
{
$nick = $data[1];
$c_data[$client[$i]]['nick'] = $nick;
// does the nickname meet the guidlines?
if (!preg_match("/^[a-zA-Z`_\{\}\[\]\^|\\-]+[a-zA-Z0-9`_\{\}\[\]\^|\\-]*/", $nick))
{
socket_write($client[$i], ":" . SERVERNAME . " 432 $nick :$newnick Erroneous nickname\r\n");
}
else
{
$goodnick = 1;
}
if ($goodnick)
{
// check to see if the nickname is in use
for ($j = 0;$j <= $maxi;$j++)
{
if ((strtolower($c_data[$client[$j]]['nick']) == strtolower($nick)) && ($client[$j] != $client[$i]))
{
socket_write($client[$i], ":" . SERVERNAME . " 433 $nick :Nickname is already in use\r\n");
unset($goodnick);
$done = 1;
}
if ($done) break;
}
}
}
if ($goodnick)
{
$data = trim(socket_read($client[$i], MAXLINE));
$data = explode(" ", $data);
if ($data[0] == "USER")
{
$c_data[$client[$i]]['user'] = $data[1];
if (gethostbyaddr($remote_host[$i]) == $remote_host[$i])
{
socket_write($client[$i], ":" . SERVERNAME . " NOTICE AUTH :*** Couldn't resolve your hostname, using IP instead...\r\n");
$addr = $remote_host[$i];
$c_data[$client[$i]]['addr'] = $addr;
}
else
{
$c_data[$client[$i]]['addr'] = gethostbyaddr($remote_host[$i]);
}
$c_data[$client[$i]]['host'] = $remote_host[$i];
$c_data[$client[$i]]['idle'] = time();
$c_data[$client[$i]]['join'] = time();
$c_data[$client[$i]]['lping'] = time();
$user = $c_data[$client[$i]]['user'];
$addr = $c_data[$client[$i]]['addr'];
}
$realname = str_replace(":", "", $data[4]);
for ($r = 5;$r <= count($data);$r++)
{
$realname .= " " . $data[$r];
}
$c_data[$client[$i]]['rname'] = $realname;
$rname = $c_data[$client[$i]]['rname'];
send_nick($client[$i], $nick);
socket_write($client[$i], ":" . SERVERNAME . " NOTICE AUTH :*** Found your hostname...\r\n");
if ($client[$i])
{
$user_current = ($user_current + 1);
$connection_count = ($connection_count + 1);
if ($user_current > $user_top)
{
$user_top = $user_current;
}
socket_write($client[$i], ":" . SERVERNAME . " 001 $nick :Welcome to the " . NETWORK . " network $nick!$user@$addr\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 002 $nick :Your host is " . SERVERNAME . ", running " . VERSION . "\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 003 $nick :This server was created " . date("r", time()) . "\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 004 $nick " . SERVERNAME . " " . VERSION . " " . MODES . "\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 005 $nick MAXCHANNELS=10 NICKLEN=15 TOPICLEN=300 KICKLEN=300 :are supported by this server\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 005 $nick CHANTYPES=# PREFIX=(ov)@+ CHANMODES=ovb,k,l,smntirc NETWORK=" . NETWORK . " :are supported by this server\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 251 $nick :There are $user_current users and $user_invs invisible on 1 servers\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 265 $nick :Current Local Users: $user_current Max: $user_top ($connection_count connections)\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 375 $nick :- " . SERVERNAME . " Message of the Day -\r\n");
socket_write($client[$i], ":" . SERVERNAME . " 272 $nick :- \r\n");
$line = file("motd.conf") or die("cannot find motd.conf!");
$num_lines = count($line);
$motd = 0;
while ($motd < $num_lines)
{
socket_write($client[$i], ":" . SERVERNAME . " 372 $nick :- " . $line[$motd] . "\r\n");
$motd++;
}
socket_write($client[$i], ":" . SERVERNAME . " 272 $nick :- \r\n");
socket_write($client[$i], ":" . SERVERNAME . " 376 $nick :End of /MOTD command.\r\n");
}
}
}
// ping handler (needs work)
function ping_user($ping_person)
{
global $c_data;
$lastping = $c_data[$ping_person]['lping'];
if ((time() - $lastping) > 180)
{
send_quit($ping_person, null, "Ping timeout\r\n");
}
else
{
socket_write($ping_person, "PING :" . SERVERNAME . "\r\n");
}
}
// handles PRIVMSG
function send_abo($person_abo, $msg)
{
global $client, $c_data, $maxi;
$message = explode(" ", $msg);
$channel = $message[1];
$msg = "";
for ($x = 2;$x <= count($message);$x++)
{
$msg .= $message[$x];
if ($message[($x + 1) ])
{
$msg .= " ";
}
}
$nick = $c_data[$person_abo]['nick'];
$user = $c_data[$person_abo]['user'];
$rname = $c_data[$person_abo]['rname'];
$addr = $c_data[$person_abo]['addr'];
if (substr($channel, 0, 1) != ("#" || "&"))
{
if ($person_abo == null)
{
send_quit($person_abo, null, "unknown error!\r\n");
}
else
{
socket_write($person_abo, ":$nick!$user@$addr PRIVMSG $channel $msg\r\n");
}
}
else
{
for ($j = 0;$j <= $maxi;$j++)
{
if ($client[$j] != null)
{
if ($nick)
{
if ($client[$j] != $person_abo)
{
if ($client[$j] == null)
{
send_quit($client[$j], null, "unknown error!\r\n");
}
else
{
socket_write($client[$j], ":$nick!$user@$addr PRIVMSG $channel $msg\r\n");
}
}
}
}
}
}
}
// handles MODE
function send_mode($person_mode, $data)
{
global $client, $c_data, $maxi, $chanlist, $list;
$nick = $c_data[$person_mode]['nick'];
$user = $c_data[$person_mode]['user'];
$rname = $c_data[$person_mode]['rname'];
$addr = $c_data[$person_mode]['addr'];
$data = explode(" ", $data);
$location = $data[1];
$mode = $data[2];
if (count($data) > 5)
{
$limit = 5;
}
else
{
$limit = count($data);
}
for ($d = 3;$d < $limit;$d++)
{
if ($d == 3)
{
$affected = $data[$d];
}
else
{
$affected .= " " . $data[$d];
}
}
// make sure the location (nick or channel) exists
if ((substr($location, 0, 1) == "#") || (substr($location, 0, 1) == "&"))
{
for ($x = 0;$x <= count($chanlist);$x++)
{
if (strtolower($chanlist[$x]) == strtolower($location))
{
$found = 1;
}
$x++;
if ($found) break;
}
if (!$found)
{
socket_write($person_mode, ":" . SERVERNAME . " 403 $nick $location :No such channel\r\n");
unset($found);
}
else
{
for ($x = 0;$x <= $maxi;$x++)
{
if (strtolower($client[$x]['nick']) == (strtolower($affected)))
{
$found = 1;
}
$x++;
if ($found) break;
}
}
if (!$found)
{
socket_write($person_mode, ":" . SERVERNAME . " 401 $nick $affected :No such nick/channel\r\n");
}
else
{
socket_write($person_mode, ":" . SERVERNAME . " 441 $nick $affected $location :They aren't on that channel\r\n");
unset($found);
}
}
// ok we're good to go!
if ($found)
{
if ($mode == ("+i" || "-i"))
{
socket_write($person_mode, ":$nick MODE $location :$mode\r\n");
if (substr($mode, 0, 1) == "+")
{
$user_invis .= ($user_invis + 1);
}
else
{
$user_invis .= ($user_invis - 1);
}
}
for ($x = 0;$x <= $maxi;$x++)
{
if (strtolower($client[$x]['nick']) == (strtolower($affected)))
{
$found = 1;
}
$x++;
if ($found) break;
}
if ($mode == ("+o" || "-o"))
{
socket_write($person_mode, ":$nick!$user@$addr MODE $location $mode $affected\r\n");
chan_nicklist_del($location, $affected);
chan_nicklist_add($location, $affected);
}
if ($mode == ("+v" || "-v"))
{
socket_write($person_mode, ":$nick!$user@$addr MODE $location $mode $affected\r\n");
chan_nicklist_del($location, $affected);
chan_nicklist_add($location, $affected);
}
else
{
$mode = str_replace("+", "", $mode);
$mode = str_replace("-", "", $mode);
socket_write($person_mode, ":" . SERVERNAME . " 472 $nick $mode :is unknown mode char to me\r\n");
}
}
}
// handles NAMES
function send_names($person_names, $c_channel)
{
global $client, $c_data, $maxi, $chan;
$nick = $c_data[$person_names]['nick'];
for ($c = 0;$c <= count($chan);$c++)
{
if ($chan[$c]['chan'] == $c_channel)
{
$found = 1;
}
if ($found) break;
}
$nicklist = $chan[$c]['list'][0];
if (count($chan[$c]['list']) > 1)
{
for ($x = 1;$x <= count($chan[$c]['list']);$x++)
{
$nicklist .= " " . $chan[$c]['list'][$x];
}
}
if (!$found)
{
socket_write($person_names, ":" . SERVERNAME . " 366 $nick $c_channel :End of /NAMES list.\r\n");
}
else
{
socket_write($person_names, ":" . SERVERNAME . " 353 $nick = $c_channel :$nicklist\r\n");
socket_write($person_names, ":" . SERVERNAME . " 366 $nick $c_channel :End of /NAMES list.\r\n");
}
}
// handles WHOIS
function send_whois($person_who, $whois)
{
global $client, $c_data, $maxi, $list;
$whois = strtolower($whois);
$nick = $c_data[$person_who]['nick'];
for ($j = 0;$j <= $maxi;$j++)
{
$w_nick = $c_data[$client[$j]]['nick'];
if (strtolower($w_nick) == $whois)
{
$found = 1;
$w_user = $c_data[$client[$j]]['user'];
$w_rname = $c_data[$client[$j]]['rname'];
$w_addr = $c_data[$client[$j]]['addr'];
$w_idle = $c_data[$client[$j]]['idle'];
$w_idle = (time() - $w_idle);
$w_join = $c_data[$client[$j]]['join'];
for ($x = 0;$x < count($list[$client[$j]]);$x++)
{
if (isset($list[$client[$j]][$x]))
{
if ($x == 0)
{
$chans = $list[$client[$j]][$x];
}
else
{
$chans .= " " . $list[$client[$j]][$x];
}
}
}
socket_write($person_who, ":" . SERVERNAME . " 311 $nick $w_nick $w_user $w_addr * :$w_rname\r\n");
if (strlen($chans) > 0)
{
socket_write($person_who, ":" . SERVERNAME . " 319 $nick $w_nick :$chans\r\n");
}
socket_write($person_who, ":" . SERVERNAME . " 312 $nick $w_nick " . SERVERNAME . " :PHIRCd v 0.1.0\r\n");
socket_write($person_who, ":" . SERVERNAME . " 317 $nick $w_nick $w_idle $w_join :seconds idle, signon time\r\n");
socket_write($person_who, ":" . SERVERNAME . " 318 $nick $w_nick :End of /WHOIS list.\r\n");
$done = 1;
}
if ($done) break;
}
if (!$found)
{
socket_write($person_who, ":" . SERVERNAME . " 401 $nick $whois :No such nick/channel\r\n");
socket_write($person_who, ":" . SERVERNAME . " 318 $nick $whois :End of /WHOIS list.\r\n");
}
}
// handles TOPIC
function send_topic($person_tpc, $msg)
{
global $client, $c_data, $maxi, $chan;
$data = explode(" ", $msg);
$channel = $data[1];
$nick = $c_data[$person_tpc]['nick'];
$user = $c_data[$person_tpc]['user'];
$rname = $c_data[$person_tpc]['rname'];
$addr = $c_data[$person_tpc]['addr'];
$topic = str_replace(":", "", $data[2]);
for ($d = 3;$d < count($data);$d++)
{
$topic .= " " . $data[$d];
}
for ($c = 0;$c <= count($chan);$c++)
{
if ($chan[$c]['chan'] == $channel)
{
$chan[$c]['topic'] = $topic;
$done = 1;
}
if ($done) break;
}
for ($j = 0;$j <= $maxi;$j++)
{
if ($client[$j] == false)
{
send_quit($client[$j], null, "unknown error!\r\n");
}
else
{
socket_write($client[$j], ":$nick!$user@$addr TOPIC $channel :$topic\r\n");
}
}
}
// handles LIST
function send_list($person_list)
{
global $client, $c_data, $maxi, $chan;
$nick = $c_data[$person_list]['nick'];
socket_write($person_list, ":" . SERVERNAME . " 321 $nick Channel :Users Name\r\n");
for ($j = 0;$j <= count($chan);$j++)
{
$channame = $chan[$j]['chan'];
$chancount = $chan[$j]['count'];
$chantopic = $chan[$j]['topic'];
socket_write($person_list, ":" . SERVERNAME . " 322 $nick $channame $chancount :$chantopic\r\n");
}
socket_write($person_list, ":" . SERVERNAME . " 323 $nick :End of /LIST\r\n");
}
// add the nick to the channel nicklist
function chan_nicklist_add($c_channel, $nick_to_add)
{
global $chan, $c_data;
$nickname = $c_data[$nick_to_add]['nick'];
for ($c = 0;$c <= count($chan);$c++)
{
if ($chan[$c]['chan'] == $c_channel)
{
for ($clist = 0;$clist <= count($chan[$c]['list']);$clist++)
{
if (strtolower($chan[$c]['list'][$clist]) == strtolower($nickname))
{
$done = 1;
break;
}
if (!isset($chan[$c]['list'][$clist]))
{
$chan[$c]['list'][$clist] = $nickname;
$chan[$c]['count'] = ($chan[$c]['count'] + 1);
$done = 1;
}
if ($done) break;
}
}
elseif (!isset($chan[$c]))
{
$chan[$c]['chan'] = $c_channel;
$chan[$c]['list'][0] = "@" . $nickname;
$chan[$c]['count'] = 1;
$x = 0;
while (!$tdone)
{
if (!isset($chanlist[$x]))
{
$chanlist[$x] = $c_channel;
$tdone = 1;
}
$x++;
}
$done = 1;
}
if ($done) break;
}
$nicklist = $chan[$c]['list'][0];
if (count($chan[$c]['list']) > 1)
{
for ($x = 1;$x <= count($chan[$c]['list']);$x++)
{
$nicklist .= " " . $chan[$c]['list'][$x];
}
}
return $nicklist;
}
// take the nickname off the channel nicklist
function chan_nicklist_del($c_channel, $nick_to_del)
{
global $chan, $c_data;
$nickname = $c_data[$nick_to_del]['nick'];
for ($c = 0;$c <= count($chan);$c++)
{
if ($chan[$c]['chan'] == $c_channel)
{
for ($x = 0;$x <= count($chan[$c]['list']);$x++)
{
if ($chan[$c]['list'][$x] == (strtolower($nickname) || "@" . strtolower($nickname) || "+" . strtolower($nickname)))
{
unset($chan[$c]['list'][$x]);
if ($x == 0)
{
unset($chan[$c]['chan']);
unset($chan[$c]['topic']);
unset($chan[$c]['count']);
unset($chan[$c]['list']);
unset($chan[$c]);
$x = 0;
while (!$done)
{
if (strtolower($chanlist[$x]) == strtolower($c_channel))
{
unset($chanlist[$x]);
$done = 1;
}
$x++;
}
}
else
{
$chan[$c]['count'] = ($chan[$c]['count'] - 1);
}
$done = 1;
}
if ($done) break;
}
}
if ($done) break;
}
}
// add channel to the nicknames channel list
function client_chanlist_add($c_channel, $person_list)
{
global $list;
if (strlen($list[$person_list]) == 0)
{
$list[$person_list][0] = $c_channel;
}
else
{
$c = 0;
while (!$done)
{
if (strtolower($list[$person_list][$c]) == strtolower($c_channel))
{
$done = 1;
}
elseif (!isset($list[$person_list][$c]))
{
$list[$person_list][$c] = $c_channel;
$done = 1;
}
$c++;
}
}
}
// take channel off clients chanlist
function client_chanlist_del($c_channel, $person_list)
{
global $list;
$c = 0;
while (!$done)
{
if (strtolower($list[$person_list][$c]) == strtolower($c_channel))
{
unset($list[$person_list][$c]);
$done = 1;
}
$c++;
}
}
// on channel join
function send_join($person_join, $msg)
{
global $client, $c_data, $maxi, $chan;
$message = explode(" ", $msg);
$channel = $message[1];
$channel = explode(",", $channel);
$nick = $c_data[$person_join]['nick'];
$user = $c_data[$person_join]['user'];
$rname = $c_data[$person_join]['rname'];
$addr = $c_data[$person_join]['addr'];
for ($c = 0;$c <= count($chan);$c++)
{
if ($chan[$c]['chan'] == $channel)
{
if ($chan[$c]['topic'])
{
$topic = $chan[$c]['topic'];
}
}
}
// tell everyone
for ($x = 0;$x < count($channel);$x++)
{
if ($person_join)
{
$jchannel = $channel[$x];
$nicklist = chan_nicklist_add($jchannel, $person_join);
client_chanlist_add($jchannel, $person_join);
for ($j = 0;$j <= $maxi;$j++)
{
if (!$client[$j])
{
send_quit($client[$j], null, "unknown error!");
}
else
{
socket_write($client[$j], ":$nick!$user@$addr JOIN :$jchannel\r\n");
}
}
socket_write($person_join, ":$nick!$user@$addr JOIN :$jchannel\r\n");
if ($topic)
{
socket_write($person_join, ":" . SERVERNAME . " 332 $nick $jchannel :$topic\r\n");
}
socket_write($person_join, ":" . SERVERNAME . " 353 $nick = $jchannel :$nicklist\r\n");
socket_write($person_join, ":" . SERVERNAME . " 366 $nick $jchannel :End of /NAMES list.\r\n");
}
}
}
// on channel part
function send_part($person_part, $msg)
{
global $client, $c_data, $maxi, $chan;
$message = explode(" ", $msg);
$channel = $message[1];
$nick = $c_data[$person_part]['nick'];
$user = $c_data[$person_part]['user'];
$rname = $c_data[$person_part]['rname'];
$addr = $c_data[$person_part]['addr'];
chan_nicklist_del($channel, $person_part);
client_chanlist_del($channel, $person_part);
// check for part message
if ($message[2])
{
$pmsg = $message[2];
}
// tell everyone
for ($j = 0;$j <= $maxi;$j++)
{
if ($pmsg)
{
if ($client[$j] == null)
{
send_quit($client[$j], null, "unknown error!");
}
else
{
socket_write($client[$j], ":$nick!$user@$addr PART $channel $pmsg\r\n");
}
}
else
{
if ($client[$j] == null)
{
send_quit($client[$j], null, "unknown error!");
}
else
{
socket_write($client[$j], ":$nick!$user@$addr PART $channel\r\n");
}
}
}
}
// on quit (or forced quit)
function send_quit($person_quit, $msg, $error = null)
{
global $client, $c_data, $remote_host, $remote_port, $i, $maxi, $list;
$message = explode(" ", $msg);
$user_current = ($user_current - 1);
// delete nickname from all channels its on
if (count($c_data[$person_nick]['chans']) > 0)
{
for ($c = 0;$c <= count($c_data[$person_nick]['chans']);$c++)
{
$channel = $c_data[$person_nick]['chans'][$c];
chan_nicklist_del($channel, $person_quit);
}
}
// put together the quit message and send it to everyone
for ($j = 0;$j <= $maxi;$j++)
{
$nick = $c_data[$person_quit]['nick'];
$user = $c_data[$person_quit]['user'];
$rname = $c_data[$person_quit]['rname'];
$addr = $c_data[$person_quit]['addr'];
if ($nick)
{
$msg = "";
for ($x = 2;$x <= count($message);$x++)
{
$msg .= $message[$x];
if ($message[($x + 1) ])
{
$msg .= ' ';
}
}
for ($x = 0;$x < count($list[$person_quit]);$x++)
{
if (isset($list[$person_quit][$x]))
{
if ($x == 0)
{
$chans = $list[$person_quit][$x];
}
else
{
$chans .= " " . $list[$person_quit][$x];
}
}
}
if (strlen($chans) > 0)
{
if ($error && $client[$j] != $person_quit)
{
socket_write($client[$j], ":$nick!$user@$addr QUIT :Quit: $error\r\n");
}
elseif ($client[$j] != $person_quit)
{
socket_write($client[$j], ":$nick!$user@$addr QUIT :Quit: $msg\r\n");
}
}
}
}
// get rid of the client information
if ($client[$i])
{
socket_close($client[$i]);
}
$client[$i] = null;
$c_data[$person_quit]['nick'] = null;
$c_data[$person_quit]['addr'] = null;
$c_data[$person_quit]['rname'] = null;
$c_data[$person_quit]['host'] = null;
$c_data[$person_quit]['user'] = null;
$c_data[$person_quit]['lping'] = null;
unset($c_data[$person_quit]['chans']);
#$c_data[$client[$i]]['throttle'] = null;
unset($c_data[$person_quit]);
unset($list[$person_quit]);
unset($remote_host[$i]);
unset($remote_port[$i]);
}
// on nickchange
function send_nick($person_nick, $newnick)
{
global $client, $c_data, $maxi;
$nick = $c_data[$person_nick]['nick'];
$user = $c_data[$person_nick]['user'];
$rname = $c_data[$person_nick]['rname'];
$addr = $c_data[$person_nick]['addr'];
if (strlen($newnick) > NICKLEN)
{
$newnick = substr($newnick, 0, NICKLEN);
}
if ($newnick != $nick)
{
// does the nickname meet the guidlines?
if (!preg_match("/^[a-zA-Z`_\{\}\[\]\^|\\-]+[a-zA-Z0-9`_\{\}\[\]\^|\\-]*/", $newnick))
{
socket_write($person_nick, ":" . SERVERNAME . " 432 $nick :$newnick Erroneous nickname\r\n");
}
else
{
$goodnick = 1;
}
if ($goodnick)
{
// check to see if the nickname is in use
for ($j = 0;$j <= $maxi;$j++)
{
if (($c_data[$client[$j]]['nick'] == $newnick) && ($c_data[$client[$j]]['nick'] != $c_data[$person_nick]['nick']))
{
socket_write($person_nick, ":" . SERVERNAME . " 433 $nick :Nickname is already in use\r\n");
$done = 1;
}
if ($done) break;
}
// change the nickname and tell everyone
if ($j >= $maxi)
{
$c_data[$person_nick]['nick'] = $newnick;
// modify all the nicklists for the channels the client is on
if (count($list[$person_nick]) > 0)
{
for ($x = 0;$x < count($list[$person_nick]);$x++)
{
$channel = $list[$person_nick][$x];
chan_nicklist_del($channel, $person_nick);
chan_nicklist_add($channel, $person_nick);
}
}
for ($j = 0;$j <= $maxi;$j++)
{
if ($client[$j] == null)
{
send_quit($client[$j], null, "unknown error!\r\n");
}
else
{
socket_write($client[$j], ":$nick!$user@$addr NICK :$newnick\r\n");
}
}
}
}
}
}
/*************************************************************
Main connection loop!
NOTE: some client support was done by Jason Greene.
*************************************************************/
$maxi = 0;
// setting up the clients (maximum client level stored in CLIENT_MAX)
for ($i = 0;$i < CLIENT_MAX;$i++)
{
$client[$i] = null;
}
while (1)
{
$rfds[0] = $socket;
// finding the first $i we can use
for ($i = 0;$i < CLIENT_MAX;$i++)
{
if ($client[$i] != null)
{
if ((time() - $c_data[$client[$i]]['lping']) > 90)
{
ping_user($client[$i]);
}
$rfds[$i + 1] = $client[$i];
}
}
// block indefinitely until we receive a connection...
if (false === $nready = socket_select($rfds, $null, $null, 5))
{
echo "socket_select() failed, reason: " . socket_strerror(socket_last_error()) . "\n";
}
elseif ($nready > 0)
{
// if we have a new connection, stick it in the $client array,
if (in_array($socket, $rfds))
{
for ($i = 0;$i < CLIENT_MAX;$i++)
{
if ($i == CLIENT_MAX - 1)
{
send_quit($client[$i], null, "Server is full!\r\n");
break;
}
// make sure client $i doesnt exist before we overwrite it
if ($client[$i] == null)
{
// connecting stuff for new client
new_client($client[$i]);
break;
}
}
// setting client count
if ($i > $maxi)
{
$maxi = $i;
}
// see if we have anymore clients connecting
if (--$nready <= 0)
{
continue;
}
}
// check the clients for incoming data.
for ($i = 0;$i <= $maxi;$i++)
{
if ($client[$i] == null)
{
continue;
}
if (in_array($client[$i], $rfds))
{
if ($client[$i] != null)
{
$info = trim(socket_read($client[$i], MAXLINE));
}
// user quit from some unknown error
if (!$info)
{
send_quit($client[$i], null, "Read error: Closing connection...\r\n");
break;
}
else
{
// setting $nick
$nick = $c_data[$client[$i]]['nick'];
// resetting idle
$c_data[$client[$i]]['idle'] = time();
// breaking $msg into segments
$data = explode(" ", $info);
// quitting
if ($data[0] == "QUIT")
{
send_quit($client[$i], $info);
}
elseif ($data[0] == "PONG" && $data[1] == ":" . SERVERNAME)
{
$c_data[$client[$i]]['lping'] = time();
}
// joining channels
elseif ($data[0] == "JOIN")
{
send_join($client[$i], $info);
}
// nick change
elseif ($data[0] == "NICK")
{
$nickchange = str_replace(":", "", $data[1]);
send_nick($client[$i], $nickchange);
}
// whois handling
elseif ($data[0] == "WHOIS")
{
send_whois($client[$i], $data[1]);
}
// parting
elseif ($data[0] == "PART")
{
send_part($client[$i], $info);
}
// message handling
elseif ($data[0] == "PRIVMSG")
{
send_abo($client[$i], $info);
}
// mode handling
elseif ($data[0] == "MODE")
{
if ($data[2])
{
send_mode($client[$i], $info);
}
}
// topic handling
elseif ($data[0] == "TOPIC")
{
send_topic($client[$i], $info);
}
// list handling
elseif ($data[0] == "LIST")
{
send_list($client[$i]);
}
// list handling
elseif ($data[0] == "NAMES")
{
send_names($client[$i], $data[1]);
}
// counting users (not accurate yet)
elseif ($data[0] == "USERCOUNT")
{
socket_write($client[$i], ":" . SERVERNAME . " NOTICE $nick :**Currently " . $user_current . " clients online**\r\n");
}
// PHIRCd information
elseif ($data[0] == "SERVERINFO")
{
socket_write($client[$i], ":" . SERVERNAME . " NOTICE $nick :**PHIRCd was written by Siron**\r\n");
}
// unknown command
elseif ($data[0])
{
$unknown = $data[0];
socket_write($client[$i], ":" . SERVERNAME . " 421 $nick $unknown :Unknown command\r\n");
}
}
// check to see if we have clients left
if (--$nready <= 0)
{
break;
}
}
}
}
}
#-EOF
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment