Last active
September 1, 2022 21:44
-
-
Save kflorence/a545757d0b6e9f6f9ca3295c8f30e798 to your computer and use it in GitHub Desktop.
An IRC daemon written in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<? | |
#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