host = $host; $this->port = $port; $this->nick = $nick; $this->pass = $pass; if($hostname) { $this->hostname = $hostname; } else { $sockname = $this->sock->getsockname(); $this->hostname = $sockname[0]; } } public function debug() { if(IRCProtocol::DEBUG) { $args = func_get_args(); $fmt = array_shift($args); $msg = vsprintf($fmt, $args); echo $msg . "\n"; } } public function connect() { parent::connect($this->host, $this->port); $this->send('NICK', $this->nick); $this->send('USER', array($this->nick, '0', $this->hostname), false, "FlaxServ php control"); return $this->token('001'); } public function send($cmd, $args=array(), $prefix=false, $data=false) { if(!is_array($args)) { $args = array($args); } array_unshift($args, $cmd); if($prefix !== false) { array_unshift($args, ':'.$prefix); } if($data !== false) { array_push($args, ':'.$data); } $msg = implode(' ', $args); $this->debug("> %s", $msg); $this->write($msg . "\r\n"); } protected function lineReceived($msg) { $this->debug("< %s", $msg); $prefix = $data = null; if($msg{0} == ':') { list($prefix, $msg) = explode(' ', substr($msg, 1), 2); } list($msg, $data) = explode(' :', $msg); $args = explode(' ', $msg); $cmd = array_shift($args); $method = sprintf("irc_%s", strtoupper($cmd)); if(method_exists($this, $method)) { call_user_func(array($this, $method), $args, $prefix, $data); } else { $this->debug("got unknown cmd '%s'", $cmd); } } private function irc_PING($args, $prefix, $data) { array_unshift($args, $this->hostname); array_push($args, $data); $this->send('PONG', $args, $this->hostname); } private function irc_PONG($args, $prefix, $data) { $this->yield('PING', $data); } private function irc_001($args, $prefix, $data) { // RPL_WELCOME - sent after successful auth $this->yield('001', true); } private function irc_433($args, $prefix, $data) { // nickname already in use $this->nick .= rand(0, 9); $this->send('NICK', $this->nick); } public function ping($dest=null) { if(!$dest) { $dest = $this->host; } $this->send('PING', $dest); return $this->token('PING'); } public function privmsg($to, $msg) { $this->send('PRIVMSG', $to, $this->nick, $msg); } } class ControlConnection extends IRCProtocol { private $nickserv; private $salt; private $cmdid = 0; public function __construct($host, $port, $nickserv, $salt, $nick="FlaxControl") { parent::__construct($host, $port, $nick); $this->nickserv = $nickserv; $this->salt = $salt; } private function sign($msg) { return md5(sprintf("%s:%s", $this->salt, $msg)); } public function cmd(/* ... */) { $args = func_get_args(); $args = array_map('rawurlencode', $args); $this->cmdid++; array_unshift($args, $this->cmdid); $cmd = implode(':', $args); $hash = $this->sign($cmd); $this->privmsg($this->nickserv, sprintf("CONTROL %s %s", $hash, $cmd)); return $this->token('CONTROL'); } public function irc_NOTICE($dest, $from, $data) { list($from) = explode('!', $from); list($what, $sig, $msg) = explode(' ', $data); if($what == 'RESPONSE' && $sig == $this->sign($msg)) { $args = explode(':', $msg); $cmdid = array_shift($args); $result = urldecode(array_shift($args)); $this->yield('CONTROL', $result); } } }