smartirc.php
来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· PHP 代码 · 共 1,982 行 · 第 1/5 页
PHP
1,982 行
while (count($rawdataar) > 0) {
$rawline = array_shift($rawdataar);
$validmessage = false;
$this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: received: "'.$rawline.'"', __FILE__, __LINE__);
// building our data packet
$ircdata = &new Net_SmartIRC_data();
$ircdata->rawmessage = $rawline;
$lineex = explode(' ', $rawline);
$ircdata->rawmessageex = $lineex;
$messagecode = $lineex[0];
if (substr($rawline, 0, 1) == ':') {
$validmessage = true;
$line = substr($rawline, 1);
$lineex = explode(' ', $line);
// conform to RFC 2812
$from = $lineex[0];
$messagecode = $lineex[1];
$exclamationpos = strpos($from, '!');
$atpos = strpos($from, '@');
$colonpos = strpos($line, ' :');
if ($colonpos !== false) {
// we want the exact position of ":" not beginning from the space
$colonpos += 1;
}
$ircdata->nick = substr($from, 0, $exclamationpos);
$ircdata->ident = substr($from, $exclamationpos+1, ($atpos-$exclamationpos)-1);
$ircdata->host = substr($from, $atpos+1);
$ircdata->type = $this->_gettype($rawline);
$ircdata->from = $from;
if ($colonpos !== false) {
$ircdata->message = substr($line, $colonpos+1);
$ircdata->messageex = explode(' ', $ircdata->message);
}
if ($ircdata->type & (SMARTIRC_TYPE_CHANNEL|
SMARTIRC_TYPE_ACTION|
SMARTIRC_TYPE_MODECHANGE|
SMARTIRC_TYPE_KICK|
SMARTIRC_TYPE_PART|
SMARTIRC_TYPE_JOIN)) {
$ircdata->channel = $lineex[2];
} else if ($ircdata->type & (SMARTIRC_TYPE_WHO|
SMARTIRC_TYPE_BANLIST|
SMARTIRC_TYPE_TOPIC|
SMARTIRC_TYPE_CHANNELMODE)) {
$ircdata->channel = $lineex[3];
} else if ($ircdata->type & SMARTIRC_TYPE_NAME) {
$ircdata->channel = $lineex[4];
}
if ($ircdata->channel !== null) {
if (substr($ircdata->channel, 0, 1) == ':') {
$ircdata->channel = substr($ircdata->channel, 1);
}
}
$this->log(SMARTIRC_DEBUG_MESSAGEPARSER, 'DEBUG_MESSAGEPARSER: ircdata nick: "'.$ircdata->nick.
'" ident: "'.$ircdata->ident.
'" host: "'.$ircdata->host.
'" type: "'.$ircdata->type.
'" from: "'.$ircdata->from.
'" channel: "'.$ircdata->channel.
'" message: "'.$ircdata->message.
'"', __FILE__, __LINE__);
}
// lets see if we have a messagehandler for it
$this->_handlemessage($messagecode, $ircdata);
if ($validmessage == true) {
// now the actionhandlers are comming
$this->_handleactionhandler($ircdata);
}
if (isset($ircdata)) {
unset($ircdata);
}
}
}
}
/**
* sends the pong for keeping alive
*
* Sends the PONG signal as reply of the PING from the IRC server.
*
* @param string $data
* @return void
* @access private
*/
function _pong($data)
{
$this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: Ping? Pong!', __FILE__, __LINE__);
$this->_send('PONG '.$data, SMARTIRC_CRITICAL);
}
/**
* returns the calculated selecttimeout value
*
* @return integer selecttimeout in microseconds
* @access private
*/
function _selecttimeout() {
if ($this->_messagebuffersize == 0) {
$this->_selecttimeout = null;
if ($this->_mintimer != false) {
$this->_calculateselecttimeout($this->_mintimer);
}
if ($this->_autoreconnect == true) {
$this->_calculateselecttimeout($this->_rxtimeout*1000);
}
$this->_calculateselecttimeout($this->_maxtimer);
return $this->_selecttimeout;
} else {
return $this->_senddelay;
}
}
/**
* calculates the selecttimeout value
*
* @return void
* @access private
*/
function _calculateselecttimeout($microseconds)
{
if (($this->_selecttimeout > $microseconds) || $this->_selecttimeout === null) {
$this->_selecttimeout = $microseconds;
}
}
/**
* updates _mintimer to the smallest timer interval
*
* @return void
* @access private
*/
function _updatemintimer()
{
$timerarray = array();
foreach ($this->_timehandler as $values) {
$timerarray[] = $values->interval;
}
$result = array_multisort($timerarray, SORT_NUMERIC, SORT_ASC);
if ($result == true && isset($timerarray[0])) {
$this->_mintimer = $timerarray[0];
} else {
$this->_mintimer = false;
}
}
/**
* reorders the actionhandler array, needed after removing one
*
* @return void
* @access private
*/
function _reorderactionhandler()
{
$orderedactionhandler = array();
foreach ($this->_actionhandler as $value) {
$orderedactionhandler[] = $value;
}
$this->_actionhandler = &$orderedactionhandler;
}
/**
* reorders the timehandler array, needed after removing one
*
* @return void
* @access private
*/
function _reordertimehandler()
{
$orderedtimehandler = array();
foreach ($this->_timehandler as $value) {
$orderedtimehandler[] = $value;
}
$this->_timehandler = &$orderedtimehandler;
}
/**
* reorders the modules array, needed after removing one
*
* @return void
* @access private
*/
function _reordermodules()
{
$orderedmodules = array();
foreach ($this->_modules as $value) {
$orderedmodules[] = $value;
}
$this->_modules = &$orderedmodules;
}
/**
* determines the messagetype of $line
*
* Analyses the type of an IRC message and returns the type.
*
* @param string $line
* @return integer SMARTIRC_TYPE_* constant
* @access private
*/
function _gettype($line)
{
if (preg_match('/^:[^ ]+? [0-9]{3} .+$/', $line) == 1) {
$lineex = explode(' ', $line);
$code = $lineex[1];
switch ($code) {
case SMARTIRC_RPL_WELCOME:
case SMARTIRC_RPL_YOURHOST:
case SMARTIRC_RPL_CREATED:
case SMARTIRC_RPL_MYINFO:
case SMARTIRC_RPL_BOUNCE:
return SMARTIRC_TYPE_LOGIN;
case SMARTIRC_RPL_LUSERCLIENT:
case SMARTIRC_RPL_LUSEROP:
case SMARTIRC_RPL_LUSERUNKNOWN:
case SMARTIRC_RPL_LUSERME:
case SMARTIRC_RPL_LUSERCHANNELS:
return SMARTIRC_TYPE_INFO;
case SMARTIRC_RPL_MOTDSTART:
case SMARTIRC_RPL_MOTD:
case SMARTIRC_RPL_ENDOFMOTD:
return SMARTIRC_TYPE_MOTD;
case SMARTIRC_RPL_NAMREPLY:
case SMARTIRC_RPL_ENDOFNAMES:
return SMARTIRC_TYPE_NAME;
case SMARTIRC_RPL_WHOREPLY:
case SMARTIRC_RPL_ENDOFWHO:
return SMARTIRC_TYPE_WHO;
case SMARTIRC_RPL_LISTSTART:
return SMARTIRC_TYPE_NONRELEVANT;
case SMARTIRC_RPL_LIST:
case SMARTIRC_RPL_LISTEND:
return SMARTIRC_TYPE_LIST;
case SMARTIRC_RPL_BANLIST:
case SMARTIRC_RPL_ENDOFBANLIST:
return SMARTIRC_TYPE_BANLIST;
case SMARTIRC_RPL_TOPIC:
return SMARTIRC_TYPE_TOPIC;
case SMARTIRC_RPL_WHOISUSER:
case SMARTIRC_RPL_WHOISSERVER:
case SMARTIRC_RPL_WHOISOPERATOR:
case SMARTIRC_RPL_WHOISIDLE:
case SMARTIRC_RPL_ENDOFWHOIS:
case SMARTIRC_RPL_WHOISCHANNELS:
return SMARTIRC_TYPE_WHOIS;
case SMARTIRC_RPL_WHOWASUSER:
case SMARTIRC_RPL_ENDOFWHOWAS:
return SMARTIRC_TYPE_WHOWAS;
case SMARTIRC_RPL_UMODEIS:
return SMARTIRC_TYPE_USERMODE;
case SMARTIRC_RPL_CHANNELMODEIS:
return SMARTIRC_TYPE_CHANNELMODE;
case SMARTIRC_ERR_NICKNAMEINUSE:
case SMARTIRC_ERR_NOTREGISTERED:
return SMARTIRC_TYPE_ERROR;
default:
$this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: replycode UNKNOWN ('.$code.'): "'.$line.'"', __FILE__, __LINE__);
}
}
if (preg_match('/^:.*? PRIVMSG .* :'.chr(1).'ACTION .*'.chr(1).'$/', $line) == 1) {
return SMARTIRC_TYPE_ACTION;
} else if (preg_match('/^:.*? PRIVMSG .* :'.chr(1).'.*'.chr(1).'$/', $line) == 1) {
return SMARTIRC_TYPE_CTCP;
} else if (preg_match('/^:.*? PRIVMSG (\&|\#|\+|\!).* :.*$/', $line) == 1) {
return SMARTIRC_TYPE_CHANNEL;
} else if (preg_match('/^:.*? PRIVMSG .*:.*$/', $line) == 1) {
return SMARTIRC_TYPE_QUERY;
} else if (preg_match('/^:.*? NOTICE .* :.*$/', $line) == 1) {
return SMARTIRC_TYPE_NOTICE;
} else if (preg_match('/^:.*? INVITE .* .*$/', $line) == 1) {
return SMARTIRC_TYPE_INVITE;
} else if (preg_match('/^:.*? JOIN .*$/', $line) == 1) {
return SMARTIRC_TYPE_JOIN;
} else if (preg_match('/^:.*? TOPIC .* :.*$/', $line) == 1) {
return SMARTIRC_TYPE_TOPICCHANGE;
} else if (preg_match('/^:.*? NICK .*$/', $line) == 1) {
return SMARTIRC_TYPE_NICKCHANGE;
} else if (preg_match('/^:.*? KICK .* .*$/', $line) == 1) {
return SMARTIRC_TYPE_KICK;
} else if (preg_match('/^:.*? PART .*$/', $line) == 1) {
return SMARTIRC_TYPE_PART;
} else if (preg_match('/^:.*? MODE .* .*$/', $line) == 1) {
return SMARTIRC_TYPE_MODECHANGE;
} else if (preg_match('/^:.*? QUIT :.*$/', $line) == 1) {
return SMARTIRC_TYPE_QUIT;
} else {
$this->log(SMARTIRC_DEBUG_MESSAGETYPES, 'DEBUG_MESSAGETYPES: SMARTIRC_TYPE_UNKNOWN!: "'.$line.'"', __FILE__, __LINE__);
return SMARTIRC_TYPE_UNKNOWN;
}
}
/**
* updates the current connection state
*
* @return boolean
* @access private
*/
function _updatestate()
{
$rtype = get_resource_type($this->_socket);
if ((is_resource($this->_socket)) &&
($this->_socket !== false) &&
($rtype == 'socket' || $rtype == 'Socket' || $rtype == 'stream')) {
$this->_state = true;
return true;
} else {
$this->_state = false;
$this->_loggedin = false;
return false;
}
}
/**
* returns the current connection state
*
* @return integer SMARTIRC_STATE_CONNECTED or SMARTIRC_STATE_DISCONNECTED
* @access private
*/
function _state()
{
$result = $this->_updatestate();
if ($result == true) {
return SMARTIRC_STATE_CONNECTED;
} else {
return SMARTIRC_STATE_DISCONNECTED;
}
}
/**
* tries to find a messagehandler for the received message ($ircdata) and calls it
*
* @param string $messagecode
* @param object $ircdata
* @return void
* @access private
*/
function _handlemessage($messagecode, &$ircdata)
{
$found = false;
if (is_numeric($messagecode)) {
if (!array_key_exists($messagecode, $this->nreplycodes)) {
$this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: ignoring unreconzied messagecode! "'.$messagecode.'"', __FILE__, __LINE__);
$this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: this IRC server ('.$this->_address.') doesn\'t conform to the RFC 2812!', __FILE__, __LINE__);
return;
}
$methodname = 'event_'.strtolower($this->nreplycodes[$messagecode]);
$_methodname = '_'.$methodname;
$_codetype = 'by numeric';
} else if (is_string($messagecode)) { // its not numericcode so already a name/string
$methodname = 'event_'.strtolower($messagecode);
$_methodname = '_'.$methodname;
$_codetype = 'by string';
}
// if exists call internal method for the handling
if (@method_exists($this, $_methodname)) {
$this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: calling internal method "'.get_class($this).'->'.$_methodname.'" ('.$_codetype.')', __FILE__, __LINE__);
$this->$_methodname($ircdata);
$found = true;
}
// if exist, call user defined method for the handling
if (@method_exists($this, $methodname)) {
$this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: calling user defined method "'.get_class($this).'->'.$methodname.'" ('.$_codetype.')', __FILE__, __LINE__);
$this->$methodname($ircdata);
$found = true;
}
if ($found == false) {
$this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: no method found for "'.$messagecode.'" ('.$methodname.')', __FILE__, __LINE__);
}
}
/**
*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?