Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- $ircd = new IrcdServer();
- class IrcdServer
- {
- private $socket = null;
- private $sockNum = 0;
- private $confArr = array();
- private $sockArr = array();
- private $quesArr = array();
- private $connArr = array();
- private $userArr = array();
- private $chanArr = array();
- private $operArr = array();
- private $nicktaken = false;
- public function __construct()
- {
- error_reporting(E_ALL);
- set_time_limit(0); // Run forever
- if(!file_exists('./configs.php'))
- {
- die("Error: Missing Configuration File './configs.php'");
- }
- $this->confArr = include 'configs.php';
- $this->initConnect();
- }
- private function initConnect()
- {
- // Create listen socket and bind
- $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
- $socket_bind = socket_bind($this->socket, $this->confArr['bindaddr'], $this->confArr['bindport']);
- if(false === $socket_bind)
- {
- $error_code = socket_last_error();
- $error_msg = socket_strerror($errorcode);
- die("Could not create socket $error_code $error_msg");
- }
- socket_listen($this->socket, $this->confArr['maxuser']);
- // Nonblocking socket
- socket_set_nonblock($this->socket);
- echo "Running...\r\n\r\n";
- // Main loop
- while(is_resource($this->socket))
- {
- $this->connHandler();
- }
- }
- private function connHandler()
- {
- if($x = @socket_accept($this->socket))
- { // Is there a new socket?
- // if (sizeof($this->connArr) == MAX_USERS) {
- // socket_write($x, 'Server full. Closing down.');
- //}
- //else
- //{
- $this->send(array('nick' => 'new user', 'sock' => $x), ':' . $this->confArr['hostname'] . ' NOTICE AUTH :*** Looking up your hostname...');
- socket_getpeername($x, $ip); // Get their IP
- $host = $this->dns_timeout($ip); // Reverse DNS
- socket_set_nonblock($x); // Nonblocking FTW
- $this->send(array('nick' => 'new user', 'sock' => $x), ':' . $this->confArr['hostname'] . ' NOTICE AUTH :*** Found your hostname');
- $this->connArr[] = array( // Add the user
- 'nick' => null,
- 'sock' => $x,
- 'buf' => '',
- 'ip' => $ip,
- 'ident' => null,
- 'realname' => null,
- 'host' => $host);
- $this->userArr[(int)$x] = array( // Add the info array
- 'oper' => false,
- 'cloak' => $host);
- }
- foreach($this->connArr as &$me)
- { // Loop through connections
- while(false != $c = trim($this->socket_normal_read($me['sock'])))
- { // Read packets
- echo $me['nick'] . ' <<< ' . $c . "\n"; // Log to console
- $args = explode(' ', $c); // Get params
- switch(strtoupper($args[0]))
- { // yay tabbing jump. srsly reduces file size.
- case 'NICK':
- $newnick = $args[1];
- $nicktaken = false; // Is nick in use?
- // Sometimes clients send :nick instead of nick
- if(strpos($c, ' :') !== false)
- {
- $newnick = substr($c, strpos($c, ' :') + 2);
- }
- if(!$this->validate_nick($newnick))
- { // Invalid nick
- $this->send($me, ':' . $this->confArr['hostname'] . ' 431 ' . $newnick . ' :Erroneous Nickname: You fail.');
- break;
- }
- foreach($this->connArr as $him)
- { // Check if nick is in use
- if(strtolower($him['nick']) == strtolower($newnick))
- {
- $nicktaken = true;
- }
- }
- if($nicktaken)
- { // it IS in use, after all.
- $this->send($me, ':' . $this->confArr['hostname'] . ' 433 ' . (($me['nick'] == null) ? '*' : $me['nick']) . ' ' . $newnick . ' :Nickname is already in use.');
- $this->nicktaken = true;
- break;
- }
- if($me['nick'] == null)
- { // Is this the initial NICK?
- $me['nick'] = $newnick;
- $this->send($me, 'PING :tu.madre'); // Send ping and wait for USER. The ping is highly random btw.
- if($this->nicktaken)
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 001 ' . $me['nick'] . ' : ');
- }
- }
- else
- {
- $newme = $me; // Make a new user instance that will be inserted into channel nick lists
- $newme['nick'] = $newnick;
- $sentto = array(); // Who already got the NICK?
- foreach($this->chanArr as &$channel)
- { // Looking through the channels....
- if(in_array($me, $channel['nicks']))
- { // Is said user in this channel?
- foreach($channel['nicks'] as $user)
- { // Loop through the nicks in said channel
- if(!in_array($user, $sentto))
- { // User did not get the NICK yet
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' NICK ' . $newnick);
- $sentto[] = $user;
- }
- }
- // Replace the channel listings with new nick. We need to search all the modes arrays too.
- $arrs = array('nicks', 'owners', 'protected', 'oped', 'halfoped', 'voiced');
- foreach($arrs as $arr)
- {
- if(in_array($me, $channel[$arr]))
- {
- $this->nick_removal($me['nick'], $channel[$arr]);
- $channel[$arr][] = $newme;
- }
- }
- }
- }
- $me['nick'] = $newnick;
- }
- break;
- case 'USER':
- if(sizeof($args) < 5)
- { // Not enough params
- $this->send($me, ':' . $this->confArr['hostname'] . ' 461 :USER Not enough parameters');
- break;
- }
- $newident = $args[1];
- $newrealname = $args[4];
- // Check for :
- if(strpos($c, ' :') !== false)
- {
- $newrealname = substr($c, strpos($c, ' :') + 2);
- }
- if($me['ident'] == null)
- { // You can only register once.
- if(!$this->nicktaken)
- {
- $me['ident'] = $newident;
- $me['realname'] = $newrealname;
- $config['version'] = '1.0-beta';
- $this->send($me, ':' . $this->confArr['hostname'] . ' 001 ' . $me['nick'] . ' :Welcome to the ' . $this->confArr['servname'] . ' IRC Network ' . $me['nick'] . '!' . $me['ident'] . '@' . $me['host']);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 002 ' . $me['nick'] . ' :Your host is ' . $this->confArr['hostname'] . ', running version Fusion '.$config['version']);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 003 ' . $me['nick'] . ' :This server was created Fri Jul 13 19:22:25 2007');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 004 ' . $me['nick'] . ' ' . $this->confArr['hostname'] . ' Fusion '.$config['version'].' iowghraAsORTVSxNCWqBzvdHtGp lvhopsmntikrRcaqOALQbSeIKVfMCuzNTGj');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 005 ' . $me['nick'] . ' CMDS=KNOCK,MAP,DCCALLOW,USERIP NAMESX SAFELIST HCN MAXCHANNELS=10 CHANLIMIT=#:10 MAXLIST=b:60,e:60,I:60 NICKLEN=30 CHANNELLEN=32 TOPICLEN=307 KICKLEN=307 AWAYLEN=307 MAXTARGETS=20 :are supported by this server');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 005 ' . $me['nick'] . ' WALLCHOPS WATCH=128 SILENCE=15 MODES=12 CHANTYPES=# PREFIX=(qaohv)~&@%+ CHANMODES=beI,kfL,lj,psmntirRcOAQKVCuzNSMTG NETWORK=' . $this->confArr['servname'] . ' CASEMAPPING=ascii EXTBAN=~,cqnr ELIST=MNUCT STATUSMSG=~&@%+ EXCEPTS :are supported by this server');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 005 ' . $me['nick'] . ' INVEX :are supported by this server');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 251 ' . $me['nick'] . ' :There are ' . sizeof($this->connArr) . ' user(s) and 0 invisible user(s) on 1 server(s)');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 252 ' . $me['nick'] . ' ' . sizeof($this->operArr) . ' :operator(s) online');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 254 ' . $me['nick'] . ' ' . sizeof($this->chanArr) . ' :channel(s) formed');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 255 ' . $me['nick'] . ' :I have ' . (sizeof($this->connArr)) . ' client(s) and 1 server(s)');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 265 ' . $me['nick'] . ' :Current Local Users: ' . (sizeof($this->connArr)) . ' Max: ' . (sizeof($this->connArr) + 1));
- $this->send($me, ':' . $this->confArr['hostname'] . ' 266 ' . $me['nick'] . ' :Current Global Users: ' . (sizeof($this->connArr)) . ' Max: ' . (sizeof($this->connArr) + 1));
- $this->send($me, ':' . $this->confArr['hostname'] . ' 375 ' . $me['nick'] . ' :###########################################');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 375 ' . $me['nick'] . ' :- Message of the Day -');
- $this->send($me, ':' . $this->confArr['hostname'] . ' 372 ' . $me['nick'] . ' :- ' . implode("\r\n:" . $this->confArr['hostname'] . ' 372 ' . $me['nick'] . ' :- ', explode("\n", $this->confArr['motd'])));
- $this->send($me, ':' . $this->confArr['hostname'] . ' 376 ' . $me['nick'] . ' :End of /MOTD command.');
- }
- }
- else
- { // Initial USER was already sent.
- $this->send($me, ':' . $this->confArr['hostname'] . ' 462 :You may not reregister');
- }
- break;
- case 'MOTD':
- $this->send($me, ':' . $this->connArr['hostname'] . ' 375 ' . $me['nick'] . ' :- Message of the Day -');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 372 ' . $me['nick'] . ' :- ' . implode("\r\n:" . $this->connArr['hostname'] . ' 372 ' . $me['nick'] . ' :- ', explode("\n", $this->confArr['motd'])));
- $this->send($me, ':' . $this->connArr['hostname'] . ' 376 ' . $me['nick'] . ' :End of /MOTD command.');
- break;
- case 'LUSERS':
- $this->send($me, ':' . $this->connArr['hostname'] . ' 251 ' . $me['nick'] . ' :There are ' . sizeof($this->connArr) . ' users and 1 invisible on 1 server(s)');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 252 ' . $me['nick'] . ' 1 :operator(s) online');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 254 ' . $me['nick'] . ' ' . sizeof($this->chanArr) . ' :channels formed');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 255 ' . $me['nick'] . ' :I have ' . (sizeof($this->connArr) + 1) . ' clients and 1 server(s)');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 265 ' . $me['nick'] . ' :Current Local Users: ' . (sizeof($this->connArr) + 1) . ' Max: ' . (sizeof($this->connArr) + 1));
- $this->send($me, ':' . $this->connArr['hostname'] . ' 266 ' . $me['nick'] . ' :Current Global Users: ' . (sizeof($this->connArr) + 1) . ' Max: ' . (sizeof($this->connArr) + 1));
- break;
- case 'VERSION':
- $config['version'] = '1.0-beta';
- $this->send($me, ':' . $this->connArr['hostname'] . ' 005 ' . $me['nick'] . ' Fusion '.$config['version'].' ' . $this->connArr['hostname'] . ' FinWXOoZE3');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 005 ' . $me['nick'] . ' CMDS=KNOCK,MAP,DCCALLOW,USERIP NAMESX SAFELIST HCN MAXCHANNELS=10 CHANLIMIT=#:10 MAXLIST=b:60,e:60,I:60 NICKLEN=30 CHANNELLEN=32 TOPICLEN=307 KICKLEN=307 AWAYLEN=307 MAXTARGETS=20 :are supported by this server');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 005 ' . $me['nick'] . ' WALLCHOPS WATCH=128 SILENCE=15 MODES=12 CHANTYPES=# PREFIX=(qaohv)~&@%+ CHANMODES=beI,kfL,lj,psmntirRcOAQKVCuzNSMTG NETWORK=' . $this->confArr['servname'] . ' CASEMAPPING=ascii EXTBAN=~,cqnr ELIST=MNUCT STATUSMSG=~&@%+ EXCEPTS :are supported by this server');
- $this->send($me, ':' . $this->connArr['hostname'] . ' 005 ' . $me['nick'] . ' INVEX :are supported by this server');
- break;
- case 'INVITE':
- $who = $args[1];
- $target = $args[2];
- if (isset($this->chanArr[strtolower($target)]))
- { // Does the channel even exist?
- $channel = $this->chanArr[strtolower($target)];
- if (!in_array($me, $channel['nicks']))
- { // Is user even in the channel?
- $this->send($me, ':' . $this->connArr['hostname'] . ' 442 ' . $me['nick'] . ' ' . $target . ' :You\'re not on that channel');
- break;
- }
- $found = false; // Make sure we find the target
- foreach($this->connArr as $him)
- { // Find target
- if (strtolower($him['nick']) == strtolower($who))
- {
- $found = $him;
- }
- }
- if($found === false)
- { // User offline
- $this->send($me, ':' . $this->confArr['hostname'] . ' 401 ' . $me['nick'] . ' ' . $who . ' :No such nick');
- break;
- }
- if(in_array($found, $channel['nicks']))
- { // Is target already in the channel?
- $this->send($me, ':' . $this->confArr['hostname'] . ' 443 ' . $me['nick'] . ' ' . $who . ' ' . $target . ' :is already on channel');
- break;
- }
- // Invite to channel
- $this->send($found, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' INVITE ' . $who . ' ' . $target);
- }
- else
- { // Channel does not exist!
- $this->send($me, ':' . $this->confArr['hostname'] . ' 403 ' . $me['nick'] . ' ' . $target . ' :No such nick/channel');
- break;
- }
- break;
- case 'PRIVMSG':
- $target = $args[1];
- $message = substr($c, strpos($c, ' :') + 2);
- if(isset($this->chanArr[strtolower($target)]))
- {
- foreach($this->chanArr[strtolower($target)]['nicks'] as $user)
- {
- // User is not self?
- if ($user !== $me)
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' PRIVMSG ' . $target . ' :' . $message);
- }
- }
- else
- {
- foreach($this->connArr as $him)
- { // Find target
- if (strtolower($him['nick']) == strtolower($target))
- {
- $this->send($him, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' PRIVMSG ' . $target . ' :' . $message);
- }
- }
- }
- break;
- case 'WHOIS':
- $target = $args[1];
- foreach($conn as $him)
- {
- if(strtolower($him['nick']) == strtolower($target))
- { // Find target
- $this->send($me, ':' . $this->confArr['hostname'] . ' 311 ' . $me['nick'] . ' ' . $him['nick'] . ' ' . $him['ident'] . ' ' . $this->userArr[(int)$him['sock']]['cloak'] . ' * :' . $him['realname']);
- //$this->send($me, ':' . $this->confArr['hostname'] . ' 307 ' . $me['nick'] . ' ' . $him['nick'] . ' :is a registered nick');
- $chans = array();
- foreach($this->chanArr as $channel => &$channel_arr)
- { // Looking through the channels....
- if(in_array($him, $channel_arr['nicks']))
- { // Is said user in this channel?
- $chans[] = $channel;
- }
- }
- if(count($chans) > 0)
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 319 ' . $me['nick'] . ' ' . $him['nick'] . ' :' . implode(' ', $chans));
- }
- send($me, ':' . $this->confArr['hostname'] . ' 312 ' . $me['nick'] . ' ' . $him['nick'] . ' ' . $this->confArr['hostname'] . ' :' . $this->confArr['hostname']);
- if($this->userArr[(int)$him['sock']]['oper'])
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 313 ' . $me['nick'] . ' ' . $him['nick'] . ' :is a Network Administrator');
- }
- //$this->send($me, ':' . $this->confArr['hostname'] . ' 310 ' . $me['nick'] . ' ' . $him['nick'] . ' :is available for help.
- $this->send($me, ':' . $this->confArr['hostname'] . ' 318 ' . $me['nick'] . ' ' . $him['nick'] . ' :End of /WHOIS list.');
- }
- }
- break;
- case 'OPER':
- if (count($args) == 3) {
- $user = $args[1];
- $pass = $args[2];
- if((isset($this->confArr['opers'][$user])) && ($this->confArr['opers'][$user] == $pass))
- {
- $this->userArr[(int)$me['sock']]['oper'] = true;
- $this->operArr[$me['nick']] = true;
- $this->send($me, ':' . $this->confArr['hostname'] . ' 381 ' . $me['nick'] . ' :You have entered... the Twilight Zone!');
- break;
- }
- }
- $this->send($me, ':' . $this->confArr['hostname'] . ' 491 ' . $me['nick'] . ' :Only few of mere mortals may try to enter the twilight zone');
- break;
- case 'KILL':
- if($this->userArr[(int)$me['sock']]['oper'])
- { // You have to be opered!
- if(count($args) >= 3)
- { // We need a reason
- $target = $args[1];
- $reason = $args[2];
- if(strpos($c, ' :') !== false)
- {
- $reason = substr($c, strpos($c, ' :') + 2);
- }
- foreach($this->connArr as $him)
- { // Find target
- if(strtolower($him['nick']) == strtolower($target))
- {
- $this->kill($him, 'Killed (' . $me['nick'] . ' (' . $reason . '))');
- }
- }
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 461 ' . $me['nick'] . ' KILL :Not enough parameters');
- }
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 481 ' . $me['nick'] . ' :Permission Denied- You do not have the correct IRC operator privileges');
- }
- break;
- case 'CHGHOST':
- if($this->userArr[(int)$me['sock']]['oper'])
- { // You have to be opered!
- if(count($args) >= 3)
- { // We need a target and mask
- $target = $args[1];
- $newmask = $args[2];
- foreach($conn as $him)
- { // Find target
- if(strtolower($him['nick']) == strtolower($target))
- {
- $this->userArr[(int)$him['sock']]['cloak'] = $newmask;
- }
- }
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 461 ' . $me['nick'] . ' CHGHOST :Not enough parameters');
- }
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 481 ' . $me['nick'] . ' :Permission Denied- You do not have the correct IRC operator privileges');
- }
- break;
- case 'REHASH':
- if($this->userArr[(int)$me['sock']]['oper'])
- { // You have to be opered!
- $this->confArr = include 'configs.php';
- $this->send($me, ':' . $this->confArr['hostname'] . ' 382 ' . $me['nick'] . ' configs.php :Rehashing');
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 481 ' . $me['nick'] . ' :Permission Denied- You do not have the correct IRC operator privileges');
- }
- break;
- case 'NOTICE':
- $target = $args[1];
- $message = substr($c, strpos($c, ' :') + 2);
- if(isset($this->chanArr[strtolower($target)]))
- {
- foreach($$this->chanArr[strtolower($target)]['nicks'] as $user)
- { // Find target
- if (!($user == $me))
- {
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' NOTICE ' . $target . ' :' . $message);
- }
- }
- }
- else
- {
- foreach ($this->connArr as $him)
- { // Find target
- if(strtolower($him['nick']) == strtolower($target))
- {
- $this->send($him, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' NOTICE ' . $target . ' :' . $message);
- }
- }
- }
- break;
- case 'JOIN':
- $targets = explode(',', $args[1]); // This line allows channel lists (like JOIN #a,#b,#c)
- foreach($targets as $target)
- { // Loop through each supplied channel
- if(!$this->validate_chan($target))
- { // Valid name?
- $this->send($me, ':' . $this->confArr['hostname'] . ' 403 ' . $target . ' :No such channel');
- break;
- }
- if(isset($this->chanArr[strtolower($target)]))
- { // Does the channel exist yet?
- $channel = $this->chanArr[strtolower($target)];
- if(in_array($me, $channel['nicks']))
- {
- break; // Is user already in the channel?
- }
- $names = $me['nick'];
- foreach ($channel['nicks'] as $user)
- { // Inform everyone and also build up /names
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' JOIN ' . $target);
- $chars = ''; // Handle modes
- $search = array('~' => 'owners', '&' => 'owners', '@' => 'oped', '%' => 'halfoped', '+' => 'voiced');
- foreach($search as $search_char => $search_name)
- {
- if(in_array($user, $channel[$search_name]))
- {
- $chars .= $search_char;
- }
- }
- $names .= ' ' . $chars . $user['nick'];
- }
- }
- else
- { // Make a new channel
- $channel = array('name' => strtolower($target), 'nicks' => array(), 'bans' => array(), 'excepts' => array(), 'invites' => array(), 'owners' => array(), 'protected' => array(), 'oped' => array($me), 'halfoped' => array(), 'voiced' => array(), 'modes' => 'nt');
- $this->chanArr[strtolower($target)] = $channel;
- $names = '@' . $me['nick']; // User is oped
- }
- $channel['nicks'][] = $me; // Add user to nicklist
- $this->send($me, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' JOIN ' . $target);
- if(isset($channel['topic']))
- { // Send topic, if any
- $this->send($me, ':' . $this->confArr['hostname'] . ' 332 ' . $me['nick'] . ' ' . $target . ' :' . $channel['topic']);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 333 ' . $me['nick'] . ' ' . $target . ' ' . $channel['topic_who'] . ' ' . $channel['topic_time']);
- }
- $this->send($me, ':' . $this->confArr['hostname'] . ' 353 ' . $me['nick'] . ' = ' . $target . ' :' . $names);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 366 ' . $me['nick'] . ' ' . $target . ' :End of /NAMES list.');
- $this->chanArr[strtolower($target)] = $channel;
- }
- break;
- case 'TOPIC':
- $target = $args[1];
- if(isset($this->chanArr[strtolower($target)]))
- { // Does the channel exist?
- $channel = $this->chanArr[strtolower($target)];
- if(strpos($c, ' :') === false)
- { // Not setting topic.
- if(isset($channel['topic']))
- { // Send topic, damnit!
- $this->send($me, ':' . $this->confArr['hostname'] . ' 332 ' . $me['nick'] . ' ' . $target . ' :' . $channel['topic']);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 333 ' . $me['nick'] . ' ' . $target . ' ' . $channel['topic_who'] . ' ' . $channel['topic_time']);
- }
- else
- { // There isn't a topic yet.
- $this->send($me, ':' . $this->confArr['hostname'] . ' 331 ' . $me['nick'] . ' ' . $target . ' :No topic is set.');
- }
- }
- else
- { // Setting the topic! fun!
- $message = substr($c, strpos($c, ' :') + 2);
- $channel['topic'] = $message;
- $channel['topic_time'] = time();
- $channel['topic_who'] = $me['nick'];
- foreach($channel['nicks'] as $user)
- { // Inform of new topic
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' TOPIC ' . $target . ' :' . $message);
- }
- $this->chanArr[strtolower($target)] = $channel;
- }
- }
- else
- { // No such channel.
- $this->send($me, ':' . $this->confArr['hostname'] . ' 403 ' . $me['nick'] . ' ' . $target . ' :No such channel');
- }
- break;
- case 'MODE': // TODO: Code mode setting!
- $target = $args[1];
- if(isset($this->chanArr[strtolower($target)]))
- {// Channel exist?
- $channel = $this->chanArr[strtolower($target)];
- if(sizeof($args) == 2)
- { // Getting modes, yay
- $this->send($me, ':' . $this->confArr['hostname'] . ' 324 ' . $me['nick'] . ' ' . $target . ' +' . $channel['modes']);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 329 ' . $me['nick'] . ' ' . $target . ' ' . time());
- }
- else
- { // Still working on this, settings modes. ATM dones't do much.
- //var_dump($args);
- $mode_args = array_slice($args, 3);
- $modes = $args[2];
- //var_dump($mode_args);
- $mode_changes = '';
- $mode_change_args = array();
- $mode_change_sign = -1;
- $sign = true;
- $oped = in_array($me, $channel['oped']);
- for($i = 0; $i < strlen($modes); $i++)
- { // Loop through each charactor in the mode request
- $char = $modes{$i};
- switch($char)
- { // Go by which char it is!
- case '+': // Set sign to ON
- $sign = true;
- break;
- case '-': // Set sign to OFF
- $sign = false;
- break;
- case 'o': // Op or deop
- if($oped)
- {
- $found = false;
- $mode_target = strtolower(array_shift($mode_args));
- foreach($channel['nicks'] as $user)
- { // Look for target
- if(strtolower($user['nick']) == $mode_target)
- {
- $found = $user;
- }
- }
- if($found !== false)
- {
- if($mode_change_sign == $sign)
- {
- $mode_changes = 'o';
- }
- if($mode_change_sign == !$sign)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'o';
- }
- if($mode_change_sign == -1)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'o';
- }
- $mode_change_args[] = $found['nick'];
- if($sign && !in_array($found, $channel['oped']))
- {
- $channel['oped'][] = $found;
- }
- if(!$sign && in_array($found, $channel['oped']))
- {
- $this->nick_removal($found['nick'], $channel['oped']);
- }
- }
- }
- break;
- case 'v': // Voice/devoice
- if($oped)
- {
- $found = false;
- $mode_target = strtolower(array_shift($mode_args));
- foreach($channel['nicks'] as $user)
- { // Look for target
- if(strtolower($user['nick']) == $mode_target)
- {
- $found = $user;
- }
- }
- if($found !== false)
- {
- if ($mode_change_sign == $sign)
- {
- $mode_changes = 'v';
- }
- if ($mode_change_sign == !$sign)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'v';
- }
- if ($mode_change_sign == -1)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'v';
- }
- $mode_change_args[] = $found['nick'];
- if ($sign && !in_array($found, $channel['voiced']))
- {
- $channel['voiced'][] = $found;
- }
- if (!$sign && in_array($found, $channel['voiced']))
- {
- $this->nick_removal($found['nick'], $channel['voiced']);
- }
- }
- }
- break;
- }
- }
- /* $message = substr($c, strpos($c, ' :') + 2);
- $channel['topic'] = $message;
- $channel['topic_time'] = time();
- $channel['topic_who'] = $me['nick']; */
- if($mode_changes != '')
- {
- foreach($channel['nicks'] as $user)
- {
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' MODE ' . $target . ' ' . $mode_changes . ' ' . implode(' ', $mode_change_args));
- }
- $this->chanArr[strtolower($target)] = $channel;
- }
- }
- }
- else
- { // No such channel (nick mdoes are not coded for yet)
- $this->send($me, ':' . $this->confArr['hostname'] . ' 403 ' . $me['nick'] . ' ' . $target . ' :No such channel');
- }
- break;
- case 'SAMODE': // TODO: Code mode setting!
- if($this->userArr[(int)$me['sock']]['oper'])
- { // You have to be opered!
- if(count($args) >= 3)
- { // We need a target and modes
- $target = $args[1];
- if(isset($this->chanArr[strtolower($target)]))
- {// Channel exist?
- $channel = $this->chanArr[strtolower($target)];
- if(sizeof($args) == 2)
- { // Getting modes, yay
- $this->send($me, ':' . $this->confArr['hostname'] . ' 324 ' . $me['nick'] . ' ' . $target . ' +' . $channel['modes']);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 329 ' . $me['nick'] . ' ' . $target . ' ' . time());
- }
- else
- { // Still working on this, settings modes. ATM dones't do much.
- //var_dump($args);
- $mode_args = array_slice($args, 3);
- $modes = $args[2];
- //var_dump($mode_args);
- $mode_changes = '';
- $mode_change_args = array();
- $mode_change_sign = -1;
- $sign = true;
- for($i = 0; $i < strlen($modes); $i++)
- { // Loop through each charactor in the mode request
- $char = $modes{$i};
- switch($char)
- { // Go by which char it is!
- case '+': // Set sign to ON
- $sign = true;
- break;
- case '-': // Set sign to OFF
- $sign = false;
- break;
- case 'o': // Op or deop
- $found = false;
- $mode_target = strtolower(array_shift($mode_args));
- foreach($channel['nicks'] as $user)
- { // Look for target
- if (strtolower($user['nick']) == $mode_target)
- {
- $found = $user;
- }
- }
- if ($found !== false)
- {
- if ($mode_change_sign == $sign)
- {
- $mode_changes = 'o';
- }
- if ($mode_change_sign == !$sign)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'o';
- }
- if ($mode_change_sign == -1)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'o';
- }
- $mode_change_args[] = $found['nick'];
- if ($sign && !in_array($found, $channel['oped']))
- {
- $channel['oped'][] = $found;
- }
- if (!$sign && in_array($found, $channel['oped']))
- {
- $this->nick_removal($found['nick'], $channel['oped']);
- }
- }
- break;
- case 'v': // Voice/devoice
- $found = false;
- $mode_target = strtolower(array_shift($mode_args));
- foreach($channel['nicks'] as $user)
- { // Look for target
- if(strtolower($user['nick']) == $mode_target)
- {
- $found = $user;
- }
- }
- if($found !== false)
- {
- if($mode_change_sign == $sign)
- {
- $mode_changes = 'v';
- }
- if($mode_change_sign == !$sign)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'v';
- }
- if($mode_change_sign == -1)
- {
- $mode_change_sign == $sign;
- $mode_changes = ($sign ? '+' : '-') . 'v';
- }
- $mode_change_args[] = $found['nick'];
- if($sign && !in_array($found, $channel['voiced']))
- {
- $channel['voiced'][] = $found;
- }
- if(!$sign && in_array($found, $channel['voiced']))
- {
- $this->nick_removal($found['nick'], $channel['voiced']);
- }
- }
- break;
- }
- }
- /* $message = substr($c, strpos($c, ' :') + 2);
- $channel['topic'] = $message;
- $channel['topic_time'] = time();
- $channel['topic_who'] = $me['nick']; */
- if($mode_changes != '')
- {
- foreach($channel['nicks'] as $user)
- {
- $this->send($user, ':' . $this->confArr['hostname'] . ' MODE ' . $target . ' ' . $mode_changes . ' ' . implode(' ', $mode_change_args));
- }
- $this->chanArr[strtolower($target)] = $channel;
- }
- }
- }
- else
- { // No such channel (nick mdoes are not coded for yet)
- $this->send($me, ':' . $this->confArr['hostname'] . ' 403 ' . $me['nick'] . ' ' . $target . ' :No such channel');
- }
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 461 ' . $me['nick'] . ' SAMODE :Not enough parameters');
- }
- }
- else
- {
- $this->send($me, ':' . $this->confArr['hostname'] . ' 481 ' . $me['nick'] . ' :Permission Denied- You do not have the correct IRC operator privileges');
- }
- break;
- case 'QUIT': // Nice and simple due to the kill() function. FUNCTIONS FTW!
- $message = 'Client exited';
- if(strpos($c, ' :') !== false)
- {
- $message = 'Quit: ' . substr($c, strpos($c, ' :') + 2);
- }
- foreach($this->operArr as $oper)
- {
- if(isset($this->operArr[$me['nick']]))
- {
- unset($this->operArr[$me['nick']]);
- }
- }
- $this->kill($me, $message);
- break;
- case 'USERHOST': // Return user's hostname.
- $this->send($me, ':' . $this->confArr['hostname'] . ' 302 ' . $me['nick'] . ' :' . $me['nick'] . '=+' . $me['ident'] . '@' . $me['host']);
- break;
- case 'PART': // TODO: Code lists (#a,#b,#c)
- $target = $args[1];
- $message = '';
- if(strpos($c, ' :') !== false)
- {
- $message = substr($c, strpos($c, ' :'));
- }
- // O RLY? (Does the channel even exist?)
- if(isset($this->chanArr[strtolower($target)]))
- { // YA RLY
- $channel = $this->chanArr[strtolower($target)];
- if(!in_array($me, $channel['nicks']))
- { // Make sure the user is there....
- $this->send($me, ':' . $this->confArr['hostname'] . ' 442 ' . $me['nick'] . ' ' . $target . ' :You\'re not on that channel');
- break;
- }
- foreach($channel['nicks'] as $user)
- { // Tell everyone about the part! But not about the whole.
- $this->send($user, ':' . $me['nick'] . '!' . $me['ident'] . '@' . $this->userArr[(int)$me['sock']]['cloak'] . ' PART ' . $target . $message);
- }
- }
- else
- { // NO RLY
- $this->send($me, ':' . $this->confArr['hostname'] . ' 403 ' . $me['nick'] . ' ' . $target . ' :No such channel');
- break;
- }
- // Remove from channel listings. We need to search all the modes arrays too.
- $arrs = array('nicks', 'owners', 'protected', 'oped', 'halfoped', 'voiced');
- foreach($arrs as $arr)
- {
- $this->nick_removal($me['nick'], $channel[$arr]);
- }
- $this->chanArr[strtolower($target)] = $channel; // Might not be needed if I used a & up there ^^ but who cares?
- break;
- case 'NAMES':
- $target = $args[1];
- $names = '';
- if(isset($this->chanArr[strtolower($target)]))
- { // If channel exists....
- $channel = $this->chanArr[strtolower($target)];
- foreach ($channel['nicks'] as $user)
- { // Build list.
- $chars = '';
- $search = array('~' => 'owners', '&' => 'owners', '@' => 'oped', '%' => 'halfoped', '+' => 'voiced');
- foreach($search as $search_char => $search_name)
- {
- if(in_array($user, $channel[$search_name]))
- {
- $chars .= $search_char;
- }
- }
- $names .= $chars . $user['nick'] . ' ';
- }
- }
- $this->send($me, ':' . $this->confArr['hostname'] . ' 353 ' . $me['nick'] . ' = ' . $target . ' :' . $names);
- $this->send($me, ':' . $this->confArr['hostname'] . ' 366 ' . $me['nick'] . ' ' . $target . ' :End of /NAMES list.');
- break;
- case 'LIST':
- foreach($this->chanArr as $chan => $chanArr)
- {
- echo "$chan\r\n";
- }
- break;
- case 'PING': // PONG DAMNIT!
- if (strpos($args[1], ':') === false)
- {
- $args[1] = ':' . $args[1];
- }
- $this->send($me, ':' . $this->confArr['hostname'] . ' PONG ' . $this->confArr['hostname'] . ' ' . $args[1]);
- break;
- } // Switch
- } // While
- } // Foreach
- sleep(1);
- }
- // Validates a nick using regex (also controls max nick length)
- private function validate_nick($nick)
- {
- return preg_match('/^[a-zA-Z\[\]_|`^][a-zA-Z0-9\[\]_|`^]{0,29}$/', $nick);
- }
- // Validates a channel name using regex (also controls max channel length)
- private function validate_chan($chan)
- {
- return preg_match('/^#[a-zA-Z0-9`~!@#$%^&*\(\)\'";|}{\]\[.<>?]{0,29}$/', $chan);
- }
- // Send a packet to a user and log to console
- private function send($who, $text)
- {
- socket_write($who['sock'], $text . "\r\n");
- echo $who['nick'] . ' >>> ' . $text . "\r\n";
- }
- // Removes a value from array, thanks to duck for providing this function
- private function array_removal($val, &$arr)
- {
- $i = array_search($val, $arr);
- if($i === false)
- {
- return false;
- }
- $arr = array_merge(array_slice($arr, 0, $i), array_slice($arr, $i + 1));
- return true;
- }
- // Removes a client with a certian nick from an array of clients, using array_removal
- private function nick_removal($nick, &$arr)
- {
- foreach($arr as $id => $him)
- {
- if(strtolower($him['nick']) == strtolower($nick))
- {
- return $this->array_removal($him, $arr);
- }
- }
- }
- // Kills a certian user, used by /kill, QUIT, netsplits, etc.
- private function kill($who, $reason)
- {
- $sentto = array($who); // Who received a QUIT packet already?
- foreach($this->chanArr as &$channel)
- { // Loop through channels
- if(in_array($who, $channel['nicks']))
- { // Was user x in this channel?
- foreach($channel['nicks'] as $user)
- { // Loop through channel nick list
- if(!in_array($user, $sentto))
- { // Make sure user didn't get QUIT yet
- $this->send($user, ':' . $who['nick'] . '!' . $who['ident'] . '@' . $this->userArr[(int)$who['sock']]['cloak'] . ' QUIT :' . $reason);
- $sentto[] = $user;
- }
- }
- $this->nick_removal($who['nick'], $channel['nicks']); // Remove the killed user from the channel
- }
- }
- $this->send($who, 'ERROR :Closing Link: ' . $who['nick'] . '[' . $who['host'] . '] (' . $reason . ')');
- socket_close($who['sock']); // Close socket
- $this->array_removal(@$this->userArr[(int)$who['sock']], $this->userArr); // Remove from the info array - part of the bugfix stated above
- $this->array_removal($who, $this->connArr); // Remove socket from listing
- }
- private function dns_timeout($ip)
- {
- $res = `nslookup -timeout=3 -retry=1 $ip`;
- if(preg_match('/\nName:(.*)\n/', $res, $out))
- {
- return trim($out[1]);
- }
- else
- {
- return $ip;
- }
- }
- private function socket_normal_read($socket)
- {
- for($i = 0; isset($this->sockArr[$i]) && $socket != $this->sockArr[$i]; $i++);
- if(!isset($this->sockArr[$i]))
- {
- $this->sockArr[$this->sockNum] = $socket;
- $this->quesArr [$this->sockNum++] = "";
- }
- $recv = @socket_read($socket, $this->confArr['maxlen']);
- //$recv = str_replace($recv, "\r", "");
- if($recv === '')
- {
- if(strpos($this->quesArr[$i], "\n") === false)
- {
- return false;
- }
- }
- elseif($recv !== false)
- {
- $this->quesArr[$i] .= $recv;
- }
- $pos = strpos($this->quesArr[$i], "\n");
- if($pos === false)
- {
- return;
- }
- $ret = substr($this->quesArr[$i], 0, $pos);
- $this->quesArr[$i] = substr($this->quesArr[$i], $pos + 1);
- return $ret;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment