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 + -
显示快捷键?