Net_SmartIRC
[ class tree: Net_SmartIRC ] [ index: Net_SmartIRC ] [ all elements ]

Source for file SmartIRC.php

Documentation is available at SmartIRC.php

  1. <?php
  2. /**
  3.  * Net_SmartIRC
  4.  * This is a PHP class for communication with IRC networks,
  5.  * which conforms to the RFC 2812 (IRC protocol).
  6.  * It's an API that handles all IRC protocol messages.
  7.  * This class is designed for creating IRC bots, chats and showing IRC related
  8.  * info on webpages.
  9.  *
  10.  * Documentation, a HOWTO, and examples are included in SmartIRC.
  11.  *
  12.  * Here you will find a service bot which I am also developing
  13.  * <http://cvs.meebey.net/atbs> and <http://cvs.meebey.net/phpbitch>
  14.  * Latest versions of Net_SmartIRC you will find on the project homepage
  15.  * or get it through PEAR since SmartIRC is an official PEAR package.
  16.  *
  17.  * Official Project Homepage: <http://pear.php.net/package/Net_SmartIRC/>
  18.  *
  19.  * Net_SmartIRC conforms to RFC 2812 (Internet Relay Chat: Client Protocol)
  20.  *
  21.  * Copyright (c) 2002-2005 Mirco Bauer <meebey@meebey.net> <http://www.meebey.net>
  22.  *
  23.  * PHP version 5
  24.  *
  25.  * Full LGPL License: <http://www.gnu.org/licenses/lgpl.txt>
  26.  *
  27.  * This library is free software; you can redistribute it and/or
  28.  * modify it under the terms of the GNU Lesser General Public
  29.  * License as published by the Free Software Foundation; either
  30.  * version 2.1 of the License, or (at your option) any later version.
  31.  *
  32.  * This library is distributed in the hope that it will be useful,
  33.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  35.  * Lesser General Public License for more details.
  36.  *
  37.  * You should have received a copy of the GNU Lesser General Public
  38.  * License along with this library; if not, write to the Free Software
  39.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  40.  *
  41.  */
  42. // ------- PHP code ----------
  43. require_once 'Net/SmartIRC/defines.php';
  44. require_once 'Net/SmartIRC/irccommands.php';
  45. require_once 'Net/SmartIRC/messagehandler.php';
  46. define('SMARTIRC_VERSION''1.1.14');
  47. define('SMARTIRC_VERSIONSTRING''Net_SmartIRC '.SMARTIRC_VERSION);
  48.  
  49. /**
  50.  * main SmartIRC class
  51.  *
  52.  * @category Net
  53.  * @package Net_SmartIRC
  54.  * @version 1.1.14
  55.  * @author clockwerx
  56.  * @author Mirco 'meebey' Bauer <meebey@meebey.net>
  57.  * @author garrettw
  58.  * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  59.  * @link http://pear.php.net/package/Net_SmartIRC
  60.  */
  61. class Net_SmartIRC extends Net_SmartIRC_messagehandler
  62. {
  63.     /**
  64.      * @var integer 
  65.      */
  66.     const DEF_AUTORETRY_MAX = 5;
  67.  
  68.     /**
  69.      * @var integer 
  70.      */
  71.     const DEF_DISCONNECT_TIME = 1000;
  72.  
  73.     /**
  74.      * @var integer 
  75.      */
  76.     const DEF_LOGFILE = 'Net_SmartIRC.log';
  77.  
  78.     /**
  79.      * @var integer 
  80.      */
  81.     const DEF_MAX_TIMER = 300000;
  82.  
  83.     /**
  84.      * @var integer 
  85.      */
  86.     const DEF_RECEIVE_DELAY = 100;
  87.  
  88.     /**
  89.      * @var integer 
  90.      */
  91.     const DEF_RECONNECT_DELAY = 10000;
  92.  
  93.     /**
  94.      * @var integer 
  95.      */
  96.     const DEF_SEND_DELAY = 250;
  97.  
  98.     /**
  99.      * @var integer 
  100.      */
  101.     const DEF_TX_RX_TIMEOUT = 300;
  102.  
  103.     /**
  104.      * @var string 
  105.      */
  106.     const IP_PATTERN = '/(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:\[[0-9A-Fa-f:]+\])|(?:[a-zA-Z0-9-_.]+)):[0-9]{1,5}/';
  107.  
  108.     /**
  109.      * @var resource 
  110.      */
  111.     protected $_socket;
  112.  
  113.     /**
  114.      * @var string 
  115.      */
  116.     protected $_address;
  117.  
  118.     /**
  119.      * @var integer 
  120.      */
  121.     protected $_port;
  122.  
  123.     /**
  124.      * @var string 
  125.      */
  126.     protected $_bindto = '0:0';
  127.  
  128.     /**
  129.      * @var string 
  130.      */
  131.     protected $_nick;
  132.  
  133.     /**
  134.      * @var string 
  135.      */
  136.     protected $_username;
  137.  
  138.     /**
  139.      * @var string 
  140.      */
  141.     protected $_realname;
  142.  
  143.     /**
  144.      * @var string 
  145.      */
  146.     protected $_usermode;
  147.  
  148.     /**
  149.      * @var string 
  150.      */
  151.     protected $_password;
  152.  
  153.     /**
  154.      * @var array 
  155.      */
  156.     protected $_performs = array();
  157.  
  158.     /**
  159.      * @var boolean 
  160.      */
  161.     protected $_state = SMARTIRC_STATE_DISCONNECTED;
  162.  
  163.     /**
  164.      * @var array 
  165.      */
  166.     protected $_actionhandler = array();
  167.  
  168.     /**
  169.      * @var array 
  170.      */
  171.     protected $_timehandler = array();
  172.  
  173.     /**
  174.      * @var integer 
  175.      */
  176.     protected $_debuglevel = SMARTIRC_DEBUG_NOTICE;
  177.  
  178.     /**
  179.      * @var array 
  180.      */
  181.     protected $_messagebuffer = array(
  182.         SMARTIRC_HIGH     => array(),
  183.         SMARTIRC_MEDIUM   => array(),
  184.         SMARTIRC_LOW       => array(),
  185.     );
  186.  
  187.     /**
  188.      * @var integer 
  189.      */
  190.     protected $_messagebuffersize;
  191.  
  192.     /**
  193.      * @var integer 
  194.      */
  195.     protected $_receivedelay = self::DEF_RECEIVE_DELAY;
  196.  
  197.     /**
  198.      * @var integer 
  199.      */
  200.     protected $_senddelay = self::DEF_SEND_DELAY;
  201.  
  202.     /**
  203.      * @var integer 
  204.      */
  205.     protected $_logdestination = SMARTIRC_STDOUT;
  206.  
  207.     /**
  208.      * @var resource 
  209.      */
  210.     protected $_logfilefp = 0;
  211.  
  212.     /**
  213.      * @var string 
  214.      */
  215.     protected $_logfile = self::DEF_LOGFILE;
  216.  
  217.     /**
  218.      * @var integer 
  219.      */
  220.     protected $_disconnecttime = self::DEF_DISCONNECT_TIME;
  221.  
  222.     /**
  223.      * @var boolean 
  224.      */
  225.     protected $_loggedin = false;
  226.  
  227.     /**
  228.      * @var boolean 
  229.      */
  230.     protected $_benchmark = false;
  231.  
  232.     /**
  233.      * @var integer 
  234.      */
  235.     protected $_benchmark_starttime;
  236.  
  237.     /**
  238.      * @var integer 
  239.      */
  240.     protected $_benchmark_stoptime;
  241.  
  242.     /**
  243.      * @var integer 
  244.      */
  245.     protected $_actionhandlerid = 0;
  246.  
  247.     /**
  248.      * @var integer 
  249.      */
  250.     protected $_timehandlerid = 0;
  251.  
  252.     /**
  253.      * @var array 
  254.      */
  255.     protected $_motd = array();
  256.  
  257.     /**
  258.      * Stores all channels in this array where we are joined, works only if channelsyncing is activated.
  259.      * Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
  260.      * $irc->getUser('#test', 'meebey')->nick;
  261.      *
  262.      * @see setChannelSyncing()
  263.      * @see Net_SmartIRC_channel
  264.      * @see Net_SmartIRC_channeluser
  265.      * @var array 
  266.      */
  267.     protected $_channels = array();
  268.  
  269.     /**
  270.      * @var boolean 
  271.      */
  272.     protected $_channelsyncing = false;
  273.  
  274.     /**
  275.      * Stores all users that had/have contact with us (channel/query/notice etc.), works only if usersyncing is activated.
  276.      * Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
  277.      * $irc->user['meebey']->host;
  278.      *
  279.      * @see setUserSyncing()
  280.      * @see Net_SmartIRC_ircuser
  281.      * @var array 
  282.      */
  283.     protected $_users = array();
  284.  
  285.     /**
  286.      * @var boolean 
  287.      */
  288.     protected $_usersyncing = false;
  289.  
  290.     /**
  291.      * Stores the path to the modules that can be loaded.
  292.      *
  293.      * @var string 
  294.      */
  295.     protected $_modulepath = '.';
  296.  
  297.     /**
  298.      * Stores all objects of the modules.
  299.      *
  300.      * @var string 
  301.      */
  302.     protected $_modules = array();
  303.  
  304.     /**
  305.      * @var string 
  306.      */
  307.     protected $_ctcpversion = SMARTIRC_VERSIONSTRING;
  308.  
  309.     /**
  310.      * @var mixed 
  311.      */
  312.     protected $_mintimer = false;
  313.  
  314.     /**
  315.      * @var integer 
  316.      */
  317.     protected $_maxtimer = self::DEF_MAX_TIMER;
  318.  
  319.     /**
  320.      * @var integer 
  321.      */
  322.     protected $_txtimeout = self::DEF_TX_RX_TIMEOUT;
  323.  
  324.     /**
  325.      * @var integer 
  326.      */
  327.     protected $_rxtimeout = self::DEF_TX_RX_TIMEOUT;
  328.  
  329.     /**
  330.      * @var integer 
  331.      */
  332.     protected $_lastrx;
  333.  
  334.     /**
  335.      * @var integer 
  336.      */
  337.     protected $_lasttx;
  338.  
  339.     /**
  340.      *
  341.      */
  342.     protected $_lastsentmsgtime = 0;
  343.  
  344.     /**
  345.      * @var integer 
  346.      */
  347.     protected $_reconnectdelay = self::DEF_RECONNECT_DELAY;
  348.  
  349.     /**
  350.      * @var boolean 
  351.      */
  352.     protected $_autoretry = false;
  353.  
  354.     /**
  355.      * @var integer 
  356.      */
  357.     protected $_autoretrymax = self::DEF_AUTORETRY_MAX;
  358.  
  359.     /**
  360.      * @var integer 
  361.      */
  362.     protected $_autoretrycount = 0;
  363.  
  364.     /**
  365.      * @var boolean 
  366.      */
  367.     protected $_connectionerror = false;
  368.  
  369.     /**
  370.      * @var boolean 
  371.      */
  372.     protected $_runasdaemon = false;
  373.  
  374.     /**
  375.      * @var boolean 
  376.      */
  377.     protected $_interrupt = false;
  378.  
  379.  
  380.     /**
  381.      * All numeric IRC replycodes, the index is the numeric replycode.
  382.      *
  383.      * @see $SMARTIRC_nreplycodes
  384.      * @var array 
  385.      */
  386.     public $nreplycodes;
  387.  
  388.     /**
  389.      * Constructor. Initiates the messagebuffer and "links" the replycodes from
  390.      * global into properties. Also some PHP runtime settings are configured.
  391.      *
  392.      * @api
  393.      * @param array $params Properties to set during instantiation
  394.      * @return object 
  395.      */
  396.     public function __construct($params = array())
  397.     {
  398.         // can't stop using the global without potentially breaking BC
  399.         $this->nreplycodes = &$GLOBALS['SMARTIRC_nreplycodes'];
  400.  
  401.         if (isset($_SERVER['REQUEST_METHOD'])) {
  402.             // the script is called from a browser, lets set default log destination
  403.             // to SMARTIRC_BROWSEROUT (makes browser friendly output)
  404.             $this->setLogDestination(SMARTIRC_BROWSEROUT);
  405.         }
  406.  
  407.         // you'll want to pass an array that includes keys like:
  408.         // ModulePath, Debug, ChannelSyncing, AutoRetry, RunAsDaemon
  409.         // so we can call their setters here
  410.         foreach ($params as $varname => $val{
  411.             $funcname 'set' $varname;
  412.             $this->$funcname($val);
  413.         }
  414.     }
  415.  
  416.     /**
  417.      * Keeps BC since private properties were once publicly accessible.
  418.      *
  419.      * @param string $name The property name asked for
  420.      * @return mixed the property's value
  421.      */
  422.     public function __get($name)
  423.     {
  424.         // PHP allows $this->getChannel($param)->memberofobject,
  425.         // but we need to not break BC.
  426.         if ($name == 'channel' || $name == 'user'):
  427.             $name '_' $name 's';
  428.         endif;
  429.         return $this->$name;
  430.     }
  431.  
  432.     /**
  433.      * Handle calls to renamed or deprecated functions
  434.      *
  435.      * @param string $method 
  436.      * @param array $args 
  437.      * @return mixed|void
  438.      */
  439.     public function __call($method$args)
  440.     {
  441.         $map = array(
  442.             'setChannelSynching'      => 'setChannelSyncing',
  443.             'setDebug'                => 'setDebugLevel',
  444.             'channel'                 => 'getChannel',
  445.             '_nicknameinuse'          => '_event_err_nicknameinuse',
  446.             'setAutoReconnect'        => '',
  447.             'setUseSockets'           => '',
  448.         );
  449.  
  450.         if (array_key_exists($method$map)) {
  451.             if (empty($map[$method])) {
  452.                 $this->log(SMARTIRC_DEBUG_NOTICE,
  453.                     "WARNING: you are using $method() which is deprecated "
  454.                     ."and no longer functional.",
  455.                     __FILE____LINE__);
  456.             else {
  457.                 $this->log(SMARTIRC_DEBUG_NOTICE,
  458.                     "WARNING: you are using $method() which is a deprecated "
  459.                     ."method, using {$map[$method]}() instead!"__FILE____LINE__);
  460.                 return call_user_func_array(array($this$map[$method])$args);
  461.             }
  462.         else {
  463.             $this->log(SMARTIRC_DEBUG_NOTICE,
  464.                 "WARNING: $method() does not exist!"__FILE____LINE__);
  465.         }
  466.     }
  467.  
  468.     /**
  469.      * Enables/disables autoretry for connecting to a server.
  470.      *
  471.      * @api
  472.      * @param boolean $boolean 
  473.      * @return boolean 
  474.      */
  475.     public function setAutoRetry($boolean)
  476.     {
  477.         return ($this->_autoretry = (bool) $boolean);
  478.     }
  479.  
  480.     /**
  481.      * Sets the maximum number of attempts to connect to a server
  482.      * before giving up.
  483.      *
  484.      * @api
  485.      * @param integer|null$autoretrymax 
  486.      * @return integer 
  487.      */
  488.     public function setAutoRetryMax($autoretrymax = null)
  489.     {
  490.         if (is_integer($autoretrymax)) {
  491.             if ($autoretrymax == 0{
  492.                 $this->setAutoRetry(false);
  493.             else {
  494.                 $this->_autoretrymax = $autoretrymax;
  495.             }
  496.         else {
  497.             $this->_autoretrymax = self::DEF_AUTORETRY_MAX;
  498.         }
  499.         return $this->_autoretrymax;
  500.     }
  501.  
  502.     /**
  503.      * Enables/disables the benchmark engine.
  504.      *
  505.      * @api
  506.      * @param boolean $boolean 
  507.      * @return boolean 
  508.      */
  509.     public function setBenchmark($boolean)
  510.     {
  511.         return ($this->_benchmark = (bool) $boolean);
  512.     }
  513.  
  514.     /**
  515.      * Sets an IP address (and optionally, a port) to bind the socket to.
  516.      *
  517.      * Limits the bot to claiming only one of the machine's IPs as its home.
  518.      * Call with no parameters to unbind.
  519.      *
  520.      * @api
  521.      * @param string $addr 
  522.      * @param int $port 
  523.      * @return string The bound address with port
  524.      */
  525.     public function setBindAddress($addr '0'$port = 0)
  526.     {
  527.         if (preg_match(self::IP_PATTERN$addr=== 0{
  528.             $addr .= ':' $port;
  529.         }
  530.         return ($this->_bindto = $addr);
  531.     }
  532.  
  533.     /**
  534.      * Enables/disables channel syncing.
  535.      *
  536.      * Channel syncing means, all users on all channel we are joined are tracked in the
  537.      * channel array. This makes it very handy for botcoding.
  538.      *
  539.      * @api
  540.      * @param boolean $boolean 
  541.      * @return boolean 
  542.      */
  543.     public function setChannelSyncing($boolean)
  544.     {
  545.         if ($boolean{
  546.             $this->_channelsyncing = true;
  547.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  548.                 'DEBUG_CHANNELSYNCING: Channel syncing enabled',
  549.                 __FILE____LINE__
  550.             );
  551.         else {
  552.             $this->_channelsyncing = false;
  553.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  554.                 'DEBUG_CHANNELSYNCING: Channel syncing disabled',
  555.                 __FILE____LINE__
  556.             );
  557.         }
  558.         return $this->_channelsyncing;
  559.     }
  560.  
  561.     /**
  562.      * Sets the CTCP version reply string.
  563.      *
  564.      * @api
  565.      * @param string $versionstring 
  566.      * @return string 
  567.      */
  568.     public function setCtcpVersion($versionstring)
  569.     {
  570.         return ($this->_ctcpversion = $versionstring);
  571.     }
  572.  
  573.     /**
  574.      * Sets the level of debug messages.
  575.      *
  576.      * Sets the debug level (bitwise), useful for testing/developing your code.
  577.      * Here the list of all possible debug levels:
  578.      * SMARTIRC_DEBUG_NONE
  579.      * SMARTIRC_DEBUG_NOTICE
  580.      * SMARTIRC_DEBUG_CONNECTION
  581.      * SMARTIRC_DEBUG_SOCKET
  582.      * SMARTIRC_DEBUG_IRCMESSAGES
  583.      * SMARTIRC_DEBUG_MESSAGETYPES
  584.      * SMARTIRC_DEBUG_ACTIONHANDLER
  585.      * SMARTIRC_DEBUG_TIMEHANDLER
  586.      * SMARTIRC_DEBUG_MESSAGEHANDLER
  587.      * SMARTIRC_DEBUG_CHANNELSYNCING
  588.      * SMARTIRC_DEBUG_MODULES
  589.      * SMARTIRC_DEBUG_USERSYNCING
  590.      * SMARTIRC_DEBUG_ALL
  591.      *
  592.      * Default: SMARTIRC_DEBUG_NOTICE
  593.      *
  594.      * @api
  595.      * @see DOCUMENTATION
  596.      * @see SMARTIRC_DEBUG_NOTICE
  597.      * @param integer $level 
  598.      * @return integer 
  599.      */
  600.     public function setDebugLevel($level)
  601.     {
  602.         return ($this->_debuglevel = $level);
  603.     }
  604.  
  605.     /**
  606.      * Sets the delaytime before closing the socket when disconnect.
  607.      *
  608.      * @api
  609.      * @param integer|null$milliseconds 
  610.      * @return integer 
  611.      */
  612.     public function setDisconnectTime($milliseconds = null)
  613.     {
  614.         if (is_integer($milliseconds)
  615.              && $milliseconds >= self::DEF_DISCONNECT_TIME
  616.         {
  617.             $this->_disconnecttime = $milliseconds;
  618.         else {
  619.             $this->_disconnecttime = self::DEF_DISCONNECT_TIME;
  620.         }
  621.         return $this->_disconnecttime;
  622.     }
  623.  
  624.     /**
  625.      * Sets the destination of all log messages.
  626.      *
  627.      * Sets the destination of log messages.
  628.      * $type can be:
  629.      * SMARTIRC_FILE for saving the log into a file
  630.      * SMARTIRC_STDOUT for echoing the log to stdout
  631.      * SMARTIRC_SYSLOG for sending the log to the syslog
  632.      * Default: SMARTIRC_STDOUT
  633.      *
  634.      * @api
  635.      * @see SMARTIRC_STDOUT
  636.      * @param integer $type must be on of the constants
  637.      * @return integer 
  638.      */
  639.     public function setLogDestination($type)
  640.     {
  641.         switch ($type{
  642.             case SMARTIRC_FILE:
  643.             case SMARTIRC_STDOUT:
  644.             case SMARTIRC_SYSLOG:
  645.             case SMARTIRC_BROWSEROUT:
  646.             case SMARTIRC_NONE:
  647.                 $this->_logdestination = $type;
  648.                 break;
  649.  
  650.             default:
  651.                 $this->log(SMARTIRC_DEBUG_NOTICE,
  652.                     'WARNING: unknown logdestination type ('.$type
  653.                     .'), will use STDOUT instead'__FILE____LINE__);
  654.                 $this->_logdestination = SMARTIRC_STDOUT;
  655.         }
  656.         return $this->_logdestination;
  657.     }
  658.  
  659.     /**
  660.      * Sets the file for the log if the destination is set to file.
  661.      *
  662.      * Sets the logfile, if {@link setLogDestination logdestination} is set to SMARTIRC_FILE.
  663.      * This should be only used with full path!
  664.      *
  665.      * @api
  666.      * @param string $file 
  667.      * @return string 
  668.      */
  669.     public function setLogFile($file)
  670.     {
  671.         return ($this->_logfile = $file);
  672.     }
  673.  
  674.     /**
  675.      * Sets the paths for the modules.
  676.      *
  677.      * @api
  678.      * @param integer $path 
  679.      * @return string 
  680.      */
  681.     public function setModulePath($path)
  682.     {
  683.         return ($this->_modulepath = $path);
  684.     }
  685.  
  686.     /**
  687.      * Sets the delay for receiving data from the IRC server.
  688.      *
  689.      * Sets the delaytime between messages that are received, this reduces your CPU load.
  690.      * Don't set this too low (min 100ms).
  691.      * Default: 100
  692.      *
  693.      * @api
  694.      * @param integer|null$milliseconds 
  695.      * @return integer 
  696.      */
  697.     public function setReceiveDelay($milliseconds = null)
  698.     {
  699.         if (is_integer($milliseconds)
  700.             && $milliseconds >= self::DEF_RECEIVE_DELAY
  701.         {
  702.             $this->_receivedelay = $milliseconds;
  703.         else {
  704.             $this->_receivedelay = self::DEF_RECEIVE_DELAY;
  705.         }
  706.         return $this->_receivedelay;
  707.     }
  708.  
  709.     /**
  710.      * Sets the delaytime before attempting reconnect.
  711.      * Value of 0 disables the delay entirely.
  712.      *
  713.      * @api
  714.      * @param integer|null$milliseconds 
  715.      * @return integer 
  716.      */
  717.     public function setReconnectDelay($milliseconds = null)
  718.     {
  719.         if (is_integer($milliseconds)) {
  720.             $this->_reconnectdelay = $milliseconds;
  721.         else {
  722.             $this->_reconnectdelay = self::DEF_RECONNECT_DELAY;
  723.         }
  724.         return $this->_reconnectdelay;
  725.     }
  726.  
  727.     /**
  728.      * Sets whether the script should be run as a daemon or not
  729.      * ( actually disables/enables ignore_user_abort() )
  730.      *
  731.      * @api
  732.      * @param boolean $boolean 
  733.      * @return boolean 
  734.      */
  735.     public function setRunAsDaemon($boolean)
  736.     {
  737.         $this->_runasdaemon = (bool) $boolean;
  738.         ignore_user_abort($this->_runasdaemon);
  739.         return $this->_runasdaemon;
  740.     }
  741.  
  742.     /**
  743.      * Sets the delay for sending data to the IRC server.
  744.      *
  745.      * Sets the delay time between sending messages, to avoid flooding
  746.      * IRC servers. If your bot has special flooding permissions on the
  747.      * network you're connected to, you can set this quite low to send
  748.      * messages faster.
  749.      * Default: 250
  750.      *
  751.      * @api
  752.      * @param integer|null$milliseconds 
  753.      * @return integer 
  754.      */
  755.     public function setSendDelay($milliseconds = null)
  756.     {
  757.         if (is_integer($milliseconds)) {
  758.             $this->_senddelay = $milliseconds;
  759.         else {
  760.             $this->_senddelay = self::DEF_SEND_DELAY;
  761.         }
  762.         return $this->_senddelay;
  763.     }
  764.  
  765.     /**
  766.      * Sets the receive timeout.
  767.      *
  768.      * If the timeout occurs, the connection will be reinitialized
  769.      * Default: 300 seconds
  770.      *
  771.      * @api
  772.      * @param integer|null$seconds 
  773.      * @return integer 
  774.      */
  775.     public function setReceiveTimeout($seconds = null)
  776.     {
  777.         if (is_integer($seconds)) {
  778.             $this->_rxtimeout = $seconds;
  779.         else {
  780.             $this->_rxtimeout = self::DEF_TX_RX_TIMEOUT;
  781.         }
  782.         return $this->_rxtimeout;
  783.     }
  784.  
  785.     /**
  786.      * Sets the transmit timeout.
  787.      *
  788.      * If the timeout occurs, the connection will be reinitialized
  789.      * Default: 300 seconds
  790.      *
  791.      * @api
  792.      * @param integer|null$seconds 
  793.      * @return integer 
  794.      */
  795.     public function setTransmitTimeout($seconds = null)
  796.     {
  797.         if (is_integer($seconds)) {
  798.             $this->_txtimeout = $seconds;
  799.         else {
  800.             $this->_txtimeout = self::DEF_TX_RX_TIMEOUT;
  801.         }
  802.         return $this->_txtimeout;
  803.     }
  804.  
  805.     /**
  806.      * Enables/disables user syncing.
  807.      *
  808.      * User syncing means, all users we have or had contact with through channel, query or
  809.      * notice are tracked in the $irc->user array. This is very handy for botcoding.
  810.      *
  811.      * @api
  812.      * @param boolean $boolean 
  813.      * @return boolean 
  814.      */
  815.     public function setUserSyncing($boolean)
  816.     {
  817.         if ($boolean{
  818.             $this->_usersyncing = true;
  819.             $this->log(SMARTIRC_DEBUG_USERSYNCING,
  820.                 'DEBUG_USERSYNCING: User syncing enabled'__FILE____LINE__);
  821.         else {
  822.             $this->_usersyncing = false;
  823.             $this->log(SMARTIRC_DEBUG_USERSYNCING,
  824.                 'DEBUG_USERSYNCING: User syncing disabled'__FILE____LINE__);
  825.         }
  826.         return $this->_usersyncing;
  827.     }
  828.  
  829.     /**
  830.      * Starts the benchmark (sets the counters).
  831.      *
  832.      * @api
  833.      * @return Net_SmartIRC 
  834.      */
  835.     public function startBenchmark()
  836.     {
  837.         $this->_benchmark_starttime = microtime(true);
  838.         $this->log(SMARTIRC_DEBUG_NOTICE'benchmark started'__FILE____LINE__);
  839.         return $this;
  840.     }
  841.  
  842.     /**
  843.      * Stops the benchmark and displays the result.
  844.      *
  845.      * @api
  846.      * @return Net_SmartIRC 
  847.      */
  848.     public function stopBenchmark()
  849.     {
  850.         $this->_benchmark_stoptime = microtime(true);
  851.         $this->log(SMARTIRC_DEBUG_NOTICE'benchmark stopped'__FILE____LINE__);
  852.  
  853.         if ($this->_benchmark{
  854.             $this->showBenchmark();
  855.         }
  856.         return $this;
  857.     }
  858.  
  859.     /**
  860.      * Shows the benchmark result.
  861.      *
  862.      * @api
  863.      * @return Net_SmartIRC 
  864.      */
  865.     public function showBenchmark()
  866.     {
  867.         $this->log(SMARTIRC_DEBUG_NOTICE'benchmark time: '
  868.             .((float)$this->_benchmark_stoptime-(float)$this->_benchmark_starttime),
  869.             __FILE____LINE__
  870.         );
  871.         return $this;
  872.     }
  873.  
  874.     /**
  875.      * Adds an entry to the log.
  876.      *
  877.      * Adds an entry to the log with Linux style log format.
  878.      * Possible $level constants (can also be combined with "|"s)
  879.      * SMARTIRC_DEBUG_NONE
  880.      * SMARTIRC_DEBUG_NOTICE
  881.      * SMARTIRC_DEBUG_CONNECTION
  882.      * SMARTIRC_DEBUG_SOCKET
  883.      * SMARTIRC_DEBUG_IRCMESSAGES
  884.      * SMARTIRC_DEBUG_MESSAGETYPES
  885.      * SMARTIRC_DEBUG_ACTIONHANDLER
  886.      * SMARTIRC_DEBUG_TIMEHANDLER
  887.      * SMARTIRC_DEBUG_MESSAGEHANDLER
  888.      * SMARTIRC_DEBUG_CHANNELSYNCING
  889.      * SMARTIRC_DEBUG_MODULES
  890.      * SMARTIRC_DEBUG_USERSYNCING
  891.      * SMARTIRC_DEBUG_ALL
  892.      *
  893.      * @api
  894.      * @see SMARTIRC_DEBUG_NOTICE
  895.      * @param integer $level bit constants (SMARTIRC_DEBUG_*)
  896.      * @param string $entry the new log entry
  897.      * @param string|null$file The source file originating the log() call
  898.      * @param int|null$line The line of code that called log()
  899.      * @return boolean 
  900.      */
  901.     public function log($level$entry$file = null$line = null)
  902.     {
  903.         // prechecks
  904.         if (!(
  905.             is_integer($level)
  906.             && ($level SMARTIRC_DEBUG_ALL)
  907.         )) {
  908.             $this->log(SMARTIRC_DEBUG_NOTICE,
  909.                 'WARNING: invalid log level passed to log() ('.$level.')',
  910.                 __FILE____LINE__
  911.             );
  912.             return false;
  913.         }
  914.  
  915.         if (!($level $this->_debuglevel)
  916.             || $this->_logdestination == SMARTIRC_NONE
  917.         {
  918.             return true;
  919.         }
  920.  
  921.         if (substr($entry-1!= "\n"{
  922.             $entry .= "\n";
  923.         }
  924.  
  925.         if ($file !== null && $line !== null{
  926.             $file basename($file);
  927.             $entry $file.'('.$line.') '.$entry;
  928.         else {
  929.             $entry 'unknown(0) '.$entry;
  930.         }
  931.  
  932.         $formattedentry date('M d H:i:s ').$entry;
  933.  
  934.         switch ($this->_logdestination{
  935.             case SMARTIRC_STDOUT:
  936.                 echo $formattedentry;
  937.                 flush();
  938.                 break;
  939.  
  940.             case SMARTIRC_BROWSEROUT:
  941.                 echo '<pre>'.htmlentities($formattedentry).'</pre>';
  942.                 break;
  943.  
  944.             case SMARTIRC_FILE:
  945.                 if (!is_resource($this->_logfilefp)) {
  946.                     if ($this->_logfilefp === null{
  947.                         // we reconncted and don't want to destroy the old log entries
  948.                         $this->_logfilefp = fopen($this->_logfile,'a');
  949.                     else {
  950.                         $this->_logfilefp = fopen($this->_logfile,'w');
  951.                     }
  952.                 }
  953.  
  954.                 fwrite($this->_logfilefp$formattedentry);
  955.                 fflush($this->_logfilefp);
  956.                 break;
  957.  
  958.             case SMARTIRC_SYSLOG:
  959.                 if (!is_int($this->_logfilefp)) {
  960.                     $this->_logfilefp = openlog('Net_SmartIRC'LOG_NDELAY,
  961.                         LOG_DAEMON
  962.                     );
  963.                 }
  964.  
  965.                 syslog(LOG_INFO$entry);
  966.         }
  967.         return true;
  968.     }
  969.  
  970.     /**
  971.      * Returns the full motd.
  972.      *
  973.      * @api
  974.      * @return array 
  975.      */
  976.     public function getMotd()
  977.     {
  978.         return $this->_motd;
  979.     }
  980.  
  981.     /**
  982.      * Returns the usermode.
  983.      *
  984.      * @api
  985.      * @return string 
  986.      */
  987.     public function getUsermode()
  988.     {
  989.         return $this->_usermode;
  990.     }
  991.  
  992.     /**
  993.      * Returns a reference to the channel object of the specified channelname.
  994.      *
  995.      * @api
  996.      * @param string $channelname 
  997.      * @return object 
  998.      */
  999.     public function &getChannel($channelname)
  1000.     {
  1001.         $err = null;
  1002.  
  1003.         if (!$this->_channelsyncing{
  1004.             $this->log(SMARTIRC_DEBUG_NOTICE,
  1005.                 'WARNING: getChannel() is called and the required Channel '
  1006.                 .'Syncing is not activated!'__FILE____LINE__
  1007.             );
  1008.             return $err;
  1009.         }
  1010.  
  1011.         if (!isset($this->_channels[strtolower($channelname)])) {
  1012.             $this->log(SMARTIRC_DEBUG_NOTICE,
  1013.                 'WARNING: getChannel() is called and the required channel '
  1014.                 .$channelname.' has not been joined!'__FILE____LINE__
  1015.             );
  1016.             return $err;
  1017.         }
  1018.  
  1019.         return $this->_channels[strtolower($channelname)];
  1020.     }
  1021.  
  1022.     /**
  1023.      * Returns a reference to the user object for the specified username and channelname.
  1024.      *
  1025.      * @api
  1026.      * @param string $channelname 
  1027.      * @param string $username 
  1028.      * @return object 
  1029.      */
  1030.     public function &getUser($channelname$username)
  1031.     {
  1032.         if (!$this->_channelsyncing{
  1033.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: getUser() is called and'
  1034.                 .' the required Channel Syncing is not activated!',
  1035.                 __FILE____LINE__
  1036.             );
  1037.             return;
  1038.         }
  1039.  
  1040.         if ($this->isJoined($channelname$username)) {
  1041.             return $this->getChannel($channelname)->users[strtolower($username)];
  1042.         }
  1043.     }
  1044.  
  1045.     /**
  1046.      * Creates the sockets and connects to the IRC server on the given port.
  1047.      *
  1048.      * Returns this SmartIRC object on success, and false on failure.
  1049.      *
  1050.      * @api
  1051.      * @param string $addr 
  1052.      * @param integer $port 
  1053.      * @param bool $reconnecting For internal use only
  1054.      * @return boolean|Net_SmartIRC
  1055.      */
  1056.     public function connect($addr$port = 6667$reconnecting = false)
  1057.     {
  1058.         ob_implicit_flush();
  1059.         $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: connecting',
  1060.             __FILE____LINE__
  1061.         );
  1062.  
  1063.         if ($hasPort preg_match(self::IP_PATTERN$addr)) {
  1064.             $colon strrpos($addr':');
  1065.             $this->_address = substr($addr0$colon);
  1066.             $this->_port = (int) substr($addr$colon + 1);
  1067.         elseif ($hasPort === 0{
  1068.             $this->_address = $addr;
  1069.             $this->_port = $port;
  1070.             $addr .= ':' $port;
  1071.         }
  1072.  
  1073.         $timeout ini_get("default_socket_timeout");
  1074.         $context stream_context_create(array('socket' => array('bindto' => $this->_bindto)));
  1075.         $this->log(SMARTIRC_DEBUG_SOCKET'DEBUG_SOCKET: binding to '.$this->_bindto,
  1076.             __FILE____LINE__);
  1077.  
  1078.  
  1079.         if ($this->_socket = stream_socket_client($addr$errno$errstr,
  1080.                 $timeoutSTREAM_CLIENT_CONNECT$context)
  1081.         {
  1082.             if (!stream_set_blocking($this->_socket0)) {
  1083.                 $this->log(SMARTIRC_DEBUG_SOCKET'DEBUG_SOCKET: unable to unblock stream',
  1084.                     __FILE____LINE__
  1085.                 );
  1086.                 $this->throwError('unable to unblock stream');
  1087.             }
  1088.  
  1089.             $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: connected',
  1090.                 __FILE____LINE__
  1091.             );
  1092.  
  1093.             $this->_autoretrycount = 0;
  1094.             $this->_connectionerror = false;
  1095.  
  1096.             $this->registerTimeHandler($this->_rxtimeout * 125$this'_pingcheck');
  1097.  
  1098.             $this->_lasttx = $this->_lastrx = time();
  1099.             $this->_updatestate();
  1100.             return $this;
  1101.         }
  1102.  
  1103.         $error_msg = "couldn't connect to \"$addr\" reason: \"$errstr ($errno)\"";
  1104.         $this->log(SMARTIRC_DEBUG_SOCKET'DEBUG_NOTICE: '.$error_msg,
  1105.             __FILE____LINE__
  1106.         );
  1107.         $this->throwError($error_msg);
  1108.  
  1109.         return ($reconnecting? false : $this->reconnect();
  1110.     }
  1111.  
  1112.     /**
  1113.      * Disconnects from the IRC server nicely with a QUIT or just destroys the socket.
  1114.      *
  1115.      * Disconnects from the IRC server in the given quickness mode.
  1116.      * $quick:
  1117.      * - true, just close the socket
  1118.      * - false, send QUIT and wait {@link $_disconnectime $_disconnectime} before
  1119.      *   closing the socket
  1120.      *
  1121.      * @api
  1122.      * @param boolean $quick default: false
  1123.      * @return boolean|Net_SmartIRC
  1124.      */
  1125.     function disconnect($quick = false)
  1126.     {
  1127.         if ($this->_updatestate(!= SMARTIRC_STATE_CONNECTED{
  1128.             return false;
  1129.         }
  1130.  
  1131.         if (!$quick{
  1132.             $this->send('QUIT'SMARTIRC_CRITICAL);
  1133.             usleep($this->_disconnecttime*1000);
  1134.         }
  1135.  
  1136.         fclose($this->_socket);
  1137.  
  1138.         $this->_updatestate();
  1139.         $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: disconnected',
  1140.             __FILE____LINE__
  1141.         );
  1142.  
  1143.         if ($this->_channelsyncing{
  1144.             // let's clean our channel array
  1145.             $this->_channels = array();
  1146.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING'DEBUG_CHANNELSYNCING: '
  1147.                 .'cleaned channel array'__FILE____LINE__
  1148.             );
  1149.         }
  1150.  
  1151.         if ($this->_usersyncing{
  1152.             // let's clean our user array
  1153.             $this->_users = array();
  1154.             $this->log(SMARTIRC_DEBUG_USERSYNCING'DEBUG_USERSYNCING: cleaned '
  1155.                 .'user array'__FILE____LINE__
  1156.             );
  1157.         }
  1158.  
  1159.         if ($this->_logdestination == SMARTIRC_FILE{
  1160.             fclose($this->_logfilefp);
  1161.             $this->_logfilefp = null;
  1162.         else if ($this->_logdestination == SMARTIRC_SYSLOG{
  1163.             closelog();
  1164.         }
  1165.  
  1166.         return $this;
  1167.     }
  1168.  
  1169.     /**
  1170.      * Reconnects to the IRC server with the same login info,
  1171.      * it also rejoins the channels
  1172.      *
  1173.      * @api
  1174.      * @return boolean|Net_SmartIRC
  1175.      */
  1176.     public function reconnect()
  1177.     {
  1178.         // remember in which channels we are joined
  1179.         $channels = array();
  1180.         foreach ($this->_channels as $value{
  1181.             if (empty($value->key)) {
  1182.                 $channels[= array('name' => $value->name);
  1183.             else {
  1184.                 $channels[= array('name' => $value->name'key' => $value->key);
  1185.             }
  1186.         }
  1187.  
  1188.         $this->disconnect(true);
  1189.  
  1190.         while ($this->_autoretry === true
  1191.             && ($this->_autoretrymax == 0 || $this->_autoretrycount < $this->_autoretrymax)
  1192.             && $this->_updatestate(!= SMARTIRC_STATE_CONNECTED
  1193.         {
  1194.             $this->_autoretrycount++;
  1195.  
  1196.             if ($this->_reconnectdelay > 0{
  1197.                 $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: delaying '
  1198.                     .'reconnect for '.$this->_reconnectdelay.' ms',
  1199.                     __FILE____LINE__
  1200.                 );
  1201.  
  1202.                 for ($i = 0; $i $this->_reconnectdelay$i++{
  1203.                     $this->_callTimeHandlers();
  1204.                     usleep(1000);
  1205.                 }
  1206.             }
  1207.  
  1208.             $this->_callTimeHandlers();
  1209.             $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: reconnecting...',
  1210.                 __FILE____LINE__
  1211.             );
  1212.  
  1213.             if ($this->connect($this->_address$this->_porttrue!== false{
  1214.                 break;
  1215.             }
  1216.         }
  1217.  
  1218.         if ($this->_updatestate(!= SMARTIRC_STATE_CONNECTED{
  1219.             return false;
  1220.         }
  1221.  
  1222.         $this->login($this->_nick$this->_realname$this->_usermode,
  1223.             $this->_username$this->_password
  1224.         );
  1225.  
  1226.         // rejoin the channels
  1227.         foreach ($channels as $value{
  1228.             if (isset($value['key'])) {
  1229.                 $this->join($value['name']$value['key']);
  1230.             else {
  1231.                 $this->join($value['name']);
  1232.             }
  1233.         }
  1234.  
  1235.         return $this;
  1236.     }
  1237.  
  1238.     /**
  1239.      * login and register nickname on the IRC network
  1240.      *
  1241.      * Registers the nickname and user information on the IRC network.
  1242.      *
  1243.      * @api
  1244.      * @param string $nick 
  1245.      * @param string $realname 
  1246.      * @param integer $usermode 
  1247.      * @param string $username 
  1248.      * @param string $password 
  1249.      * @return Net_SmartIRC 
  1250.      */
  1251.     public function login($nick$realname$usermode = 0$username = null,
  1252.         $password = null
  1253.     {
  1254.         $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: logging in',
  1255.             __FILE____LINE__
  1256.         );
  1257.  
  1258.         $this->_nick = str_replace(' '''$nick);
  1259.         $this->_realname = $realname;
  1260.  
  1261.         if ($username !== null{
  1262.             $this->_username = str_replace(' '''$username);
  1263.         else {
  1264.             $this->_username = str_replace(' '''exec('whoami'));
  1265.         }
  1266.  
  1267.         if ($password !== null{
  1268.             $this->_password = $password;
  1269.             $this->send('PASS '.$this->_passwordSMARTIRC_CRITICAL);
  1270.         }
  1271.  
  1272.         if (!is_numeric($usermode)) {
  1273.             $ipos strpos($usermode'i');
  1274.             $wpos strpos($usermode'w');
  1275.             $val = 0;
  1276.             if ($ipos$val += 8;
  1277.             if ($wpos$val += 4;
  1278.  
  1279.             if ($val == 0{
  1280.                 $this->log(SMARTIRC_DEBUG_NOTICE'DEBUG_NOTICE: login() usermode ('
  1281.                     .$usermode.') is not valid, using 0 instead',
  1282.                     __FILE____LINE__
  1283.                 );
  1284.             }
  1285.             $usermode $val;
  1286.         }
  1287.  
  1288.         $this->send('NICK '.$this->_nickSMARTIRC_CRITICAL);
  1289.         $this->send('USER '.$this->_username.' '.$usermode.' '.SMARTIRC_UNUSED
  1290.             .' :'.$this->_realnameSMARTIRC_CRITICAL
  1291.         );
  1292.  
  1293.         if (count($this->_performs)) {
  1294.             // if we have extra commands to send, do it now
  1295.             foreach ($this->_performs as $command{
  1296.                 $this->send($commandSMARTIRC_HIGH);
  1297.             }
  1298.             // if we sent "ns auth" commands, we may need to resend our nick
  1299.             $this->send('NICK '.$this->_nickSMARTIRC_HIGH);
  1300.         }
  1301.  
  1302.         return $this;
  1303.     }
  1304.  
  1305.     // </IRC methods>
  1306.  
  1307.     /**
  1308.      * adds a command to the list of commands to be sent after login() info
  1309.      *
  1310.      * @api
  1311.      * @param string $cmd the command to add to the perform list
  1312.      * @return Net_SmartIRC 
  1313.      */
  1314.     public function perform($cmd)
  1315.     {
  1316.         $this->_performs[$cmd;
  1317.         return $this;
  1318.     }
  1319.  
  1320.     /**
  1321.      * sends an IRC message
  1322.      *
  1323.      * Adds a message to the messagequeue, with the optional priority.
  1324.      * $priority:
  1325.      * SMARTIRC_CRITICAL
  1326.      * SMARTIRC_HIGH
  1327.      * SMARTIRC_MEDIUM
  1328.      * SMARTIRC_LOW
  1329.      *
  1330.      * @api
  1331.      * @param string $data 
  1332.      * @param integer $priority must be one of the priority constants
  1333.      * @return boolean|Net_SmartIRC
  1334.      */
  1335.     public function send($data$priority = SMARTIRC_MEDIUM)
  1336.     {
  1337.         switch ($priority{
  1338.             case SMARTIRC_CRITICAL:
  1339.                 $this->_rawsend($data);
  1340.                 break;
  1341.  
  1342.             case SMARTIRC_HIGH:
  1343.             case SMARTIRC_MEDIUM:
  1344.             case SMARTIRC_LOW:
  1345.                 $this->_messagebuffer[$priority][$data;
  1346.                 break;
  1347.  
  1348.             default:
  1349.                 $this->log(SMARTIRC_DEBUG_NOTICE"WARNING: message ($data"
  1350.                     ."with an invalid priority passed ($priority), message is "
  1351.                     .'ignored!'__FILE____LINE__
  1352.                 );
  1353.                 return false;
  1354.         }
  1355.  
  1356.         return $this;
  1357.     }
  1358.  
  1359.     /**
  1360.      * checks if the bot is connected
  1361.      *
  1362.      * @api
  1363.      * @return boolean 
  1364.      */
  1365.     public function isConnected()
  1366.     {
  1367.         return ($this->_updatestate(=== SMARTIRC_STATE_CONNECTED);
  1368.     }
  1369.  
  1370.     /**
  1371.      * checks if the passed nickname is our own nickname
  1372.      *
  1373.      * @api
  1374.      * @param string $nickname 
  1375.      * @return boolean 
  1376.      */
  1377.     public function isMe($nickname)
  1378.     {
  1379.         return ($nickname == $this->_nick);
  1380.     }
  1381.  
  1382.     /**
  1383.      * checks if we or the given user is joined to the specified channel and returns the result
  1384.      * ChannelSyncing is required for this.
  1385.      *
  1386.      * @api
  1387.      * @see setChannelSyncing
  1388.      * @param string $channel 
  1389.      * @param string $nickname 
  1390.      * @return boolean 
  1391.      */
  1392.     public function isJoined($channel$nickname = null)
  1393.     {
  1394.         if (!$this->_channelsyncing{
  1395.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isJoined() is called '
  1396.                 .'and the required Channel Syncing is not activated!',
  1397.                 __FILE____LINE__
  1398.             );
  1399.             return false;
  1400.         }
  1401.  
  1402.         if (!isset($this->_channels[strtolower($channel)])) {
  1403.             if ($nickname !== null{
  1404.                 $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isJoined() is called'
  1405.                     .' on a user in a channel we are not joined to!',
  1406.                     __FILE____LINE__
  1407.                 );
  1408.             }
  1409.             return false;
  1410.         }
  1411.  
  1412.         if ($nickname === null{
  1413.             return true;
  1414.         }
  1415.  
  1416.         return isset($this->getChannel($channel)->users[strtolower($nickname)]);
  1417.     }
  1418.  
  1419.     /**
  1420.      * Checks if we or the given user is founder on the specified channel and returns the result.
  1421.      * ChannelSyncing is required for this.
  1422.      *
  1423.      * @api
  1424.      * @see setChannelSyncing
  1425.      * @param string $channel 
  1426.      * @param string $nickname 
  1427.      * @return boolean 
  1428.      */
  1429.     public function isFounder($channel$nickname = null)
  1430.     {
  1431.         if (!$this->_channelsyncing{
  1432.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isFounder() is called '
  1433.                 .'and the required Channel Syncing is not activated!',
  1434.                 __FILE____LINE__
  1435.             );
  1436.             return false;
  1437.         }
  1438.  
  1439.         if ($nickname === null{
  1440.             $nickname $this->_nick;
  1441.         }
  1442.  
  1443.         return ($this->isJoined($channel$nickname)
  1444.             && $this->getUser($channel$nickname)->founder
  1445.         );
  1446.     }
  1447.  
  1448.     /**
  1449.      * Checks if we or the given user is admin on the specified channel and returns the result.
  1450.      * ChannelSyncing is required for this.
  1451.      *
  1452.      * @api
  1453.      * @see setChannelSyncing
  1454.      * @param string $channel 
  1455.      * @param string $nickname 
  1456.      * @return boolean 
  1457.      */
  1458.     public function isAdmin($channel$nickname = null)
  1459.     {
  1460.         if (!$this->_channelsyncing{
  1461.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isAdmin() is called '
  1462.                 .'and the required Channel Syncing is not activated!',
  1463.                 __FILE____LINE__
  1464.             );
  1465.             return false;
  1466.         }
  1467.  
  1468.         if ($nickname === null{
  1469.             $nickname $this->_nick;
  1470.         }
  1471.  
  1472.         return ($this->isJoined($channel$nickname)
  1473.             && $this->getUser($channel$nickname)->admin
  1474.         );
  1475.     }
  1476.  
  1477.     /**
  1478.      * Checks if we or the given user is opped on the specified channel and returns the result.
  1479.      * ChannelSyncing is required for this.
  1480.      *
  1481.      * @api
  1482.      * @see setChannelSyncing
  1483.      * @param string $channel 
  1484.      * @param string $nickname 
  1485.      * @return boolean 
  1486.      */
  1487.     public function isOpped($channel$nickname = null)
  1488.     {
  1489.         if (!$this->_channelsyncing{
  1490.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isOpped() is called '
  1491.                 .'and the required Channel Syncing is not activated!',
  1492.                 __FILE____LINE__
  1493.             );
  1494.             return false;
  1495.         }
  1496.  
  1497.         if ($nickname === null{
  1498.             $nickname $this->_nick;
  1499.         }
  1500.  
  1501.         return ($this->isJoined($channel$nickname)
  1502.             && $this->getUser($channel$nickname)->op
  1503.         );
  1504.     }
  1505.  
  1506.     /**
  1507.      * Checks if we or the given user is hopped on the specified channel and returns the result.
  1508.      * ChannelSyncing is required for this.
  1509.      *
  1510.      * @api
  1511.      * @see setChannelSyncing
  1512.      * @param string $channel 
  1513.      * @param string $nickname 
  1514.      * @return boolean 
  1515.      */
  1516.     public function isHopped($channel$nickname = null)
  1517.     {
  1518.         if (!$this->_channelsyncing{
  1519.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isHopped() is called '
  1520.                 .'and the required Channel Syncing is not activated!',
  1521.                 __FILE____LINE__
  1522.             );
  1523.             return false;
  1524.         }
  1525.  
  1526.         if ($nickname === null{
  1527.             $nickname $this->_nick;
  1528.         }
  1529.  
  1530.         return ($this->isJoined($channel$nickname)
  1531.             && $this->getUser($channel$nickname)->hop
  1532.         );
  1533.     }
  1534.  
  1535.     /**
  1536.      * Checks if we or the given user is voiced on the specified channel and returns the result.
  1537.      * ChannelSyncing is required for this.
  1538.      *
  1539.      * @api
  1540.      * @see setChannelSyncing
  1541.      * @param string $channel 
  1542.      * @param string $nickname 
  1543.      * @return boolean 
  1544.      */
  1545.     public function isVoiced($channel$nickname = null)
  1546.     {
  1547.         if (!$this->_channelsyncing{
  1548.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isVoiced() is called '
  1549.                 .'and the required Channel Syncing is not activated!',
  1550.                 __FILE____LINE__
  1551.             );
  1552.             return false;
  1553.         }
  1554.  
  1555.         if ($nickname === null{
  1556.             $nickname $this->_nick;
  1557.         }
  1558.  
  1559.         return ($this->isJoined($channel$nickname)
  1560.             && $this->getUser($channel$nickname)->voice
  1561.         );
  1562.     }
  1563.  
  1564.     /**
  1565.      * Checks if the hostmask is on the specified channel banned and returns the result.
  1566.      * ChannelSyncing is required for this.
  1567.      *
  1568.      * @api
  1569.      * @see setChannelSyncing
  1570.      * @param string $channel 
  1571.      * @param string $hostmask 
  1572.      * @return boolean 
  1573.      */
  1574.     public function isBanned($channel$hostmask)
  1575.     {
  1576.         if (!$this->_channelsyncing{
  1577.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: isBanned() is called '
  1578.                 .'and the required Channel Syncing is not activated!',
  1579.                 __FILE____LINE__
  1580.             );
  1581.             return false;
  1582.         }
  1583.  
  1584.         return ($this->isJoined($channel)
  1585.                 && array_search($hostmask$this->getChannel($channel)->bans
  1586.             !== false
  1587.         );
  1588.     }
  1589.  
  1590.     /**
  1591.      * Provides a mechanism to interrupt a listen() loop by a bot or something
  1592.      *
  1593.      * @api
  1594.      * @param bool $ival Whether to interrupt the next listen iteration
  1595.      * @return boolean 
  1596.      */
  1597.     public function interrupt($ival = true)
  1598.     {
  1599.         return ($this->_interrupt = $ival);
  1600.     }
  1601.  
  1602.     /**
  1603.      * goes into receive mode
  1604.      *
  1605.      * Goes into receive and idle mode. Only call this if you want to "spawn" the bot.
  1606.      * No further lines of PHP code will be processed after this call, only the bot methods!
  1607.      *
  1608.      * @api
  1609.      * @return Net_SmartIRC 
  1610.      */
  1611.     public function listen()
  1612.     {
  1613.         set_time_limit(0);
  1614.         while ($this->listenOnce(&& !$this->_interrupt{}
  1615.         return $this;
  1616.     }
  1617.  
  1618.     /**
  1619.      * goes into receive mode _only_ for one pass
  1620.      *
  1621.      * Goes into receive mode. It will return when one pass is complete.
  1622.      * Use this when you want to connect to multiple IRC servers.
  1623.      *
  1624.      * @api
  1625.      * @return boolean|Net_SmartIRC
  1626.      */
  1627.     public function listenOnce()
  1628.     {
  1629.         // if we're not connected, we can't listen, so return
  1630.         if ($this->_updatestate(!= SMARTIRC_STATE_CONNECTED{
  1631.             return false;
  1632.         }
  1633.  
  1634.         // before we listen...
  1635.         if ($this->_loggedin{
  1636.             // see if any timehandler needs to be called
  1637.             $this->_callTimeHandlers();
  1638.  
  1639.             // also let's send any queued messages
  1640.             if ($this->_lastsentmsgtime == 0{
  1641.                 $this->_lastsentmsgtime = microtime(true);
  1642.             }
  1643.  
  1644.             $highcount count($this->_messagebuffer[SMARTIRC_HIGH]);
  1645.             $mediumcount count($this->_messagebuffer[SMARTIRC_MEDIUM]);
  1646.             $lowcount count($this->_messagebuffer[SMARTIRC_LOW]);
  1647.             $this->_messagebuffersize = $highcount+$mediumcount+$lowcount;
  1648.  
  1649.             // don't send them too fast
  1650.             if ($this->_messagebuffersize
  1651.                 && microtime(true)
  1652.                     >= ($this->_lastsentmsgtime+($this->_senddelay/1000))
  1653.             {
  1654.                 $result = null;
  1655.                 if ($highcount{
  1656.                     $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_HIGH]));
  1657.                     $this->_lastsentmsgtime = microtime(true);
  1658.                 else if ($mediumcount{
  1659.                     $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_MEDIUM]));
  1660.                     $this->_lastsentmsgtime = microtime(true);
  1661.                 else if ($lowcount{
  1662.                     $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_LOW]));
  1663.                     $this->_lastsentmsgtime = microtime(true);
  1664.                 }
  1665.             }
  1666.         }
  1667.  
  1668.         // calculate selecttimeout
  1669.         $compare = array($this->_maxtimer$this->_receivedelay * 1000);
  1670.  
  1671.         if ($this->_mintimer{
  1672.             $compare[$this->_mintimer;
  1673.         }
  1674.  
  1675.         $selecttimeout ($this->_messagebuffersize != 0)
  1676.             ? $this->_senddelay
  1677.             : min($compare)
  1678.         ;
  1679.  
  1680.         // check the socket to see if data is waiting for us
  1681.         // this will trigger a warning when a signal is received
  1682.         $r = array($this->_socket);
  1683.         $w = null;
  1684.         $e = null;
  1685.         $result stream_select($r$w$e0$selecttimeout);
  1686.  
  1687.         $rawdata = null;
  1688.  
  1689.         if ($result{
  1690.             // the socket got data to read
  1691.             $rawdata '';
  1692.             do {
  1693.                 if ($get fgets($this->_socket)):
  1694.                     $rawdata .= $get;
  1695.                 endif;
  1696.                 $rawlen strlen($rawdata);
  1697.             while ($rawlen && $rawdata{$rawlen - 1!= "\n");
  1698.  
  1699.         else if ($result === false{
  1700.             // panic! panic! something went wrong! maybe received a signal.
  1701.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: stream_select()'
  1702.                 .' returned false, something went wrong!',
  1703.                 __FILE____LINE__
  1704.             );
  1705.             exit;
  1706.         }
  1707.         // no data on the socket
  1708.  
  1709.         $timestamp time();
  1710.         if (empty($rawdata)) {
  1711.             if ($this->_lastrx < ($timestamp $this->_rxtimeout)) {
  1712.                 $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: '
  1713.                     .'receive timeout detected, doing reconnect...',
  1714.                     __FILE____LINE__
  1715.                 );
  1716.                 $this->_connectionerror = true;
  1717.             else if ($this->_lasttx < ($timestamp $this->_txtimeout)) {
  1718.                 $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: '
  1719.                     .'transmit timeout detected, doing reconnect...',
  1720.                     __FILE____LINE__
  1721.                 );
  1722.                 $this->_connectionerror = true;
  1723.             }
  1724.         else {
  1725.             $this->_lastrx = $timestamp;
  1726.  
  1727.             // split up incoming lines, remove any empty ones and
  1728.             // trim whitespace off the rest
  1729.             $rawdataar array_map('trim'array_filter(explode("\r\n"$rawdata)));
  1730.  
  1731.             // parse and handle them
  1732.             foreach ($rawdataar as $rawline{
  1733.                 $this->log(SMARTIRC_DEBUG_IRCMESSAGES'DEBUG_IRCMESSAGES: '
  1734.                     ."received: \"$rawline\""__FILE____LINE__
  1735.                 );
  1736.  
  1737.                 // building our data packet
  1738.                 $ircdata = new Net_SmartIRC_data();
  1739.                 $ircdata->rawmessage = $rawline;
  1740.                 $ircdata->rawmessageex = explode(' '$rawline)// kept for BC
  1741.  
  1742.                 // parsing the message {
  1743.                 $prefix $trailing '';
  1744.                 $prefixEnd = -1;
  1745.  
  1746.                 // parse out the prefix
  1747.                 if ($rawline{0== ':'{
  1748.                     $prefixEnd strpos($rawline' ');
  1749.                     $prefix substr($rawline1$prefixEnd - 1);
  1750.                 }
  1751.  
  1752.                 // parse out the trailing
  1753.                 if ($trailingStart strpos($rawline' :')) // this is not ==
  1754.                     $trailing substr($rawline$trailingStart + 2);
  1755.                 else {
  1756.                     $trailingStart strlen($rawline);
  1757.                 }
  1758.  
  1759.                 // parse out command and params
  1760.                 $params explode(' 'substr($rawline,
  1761.                                               $prefixEnd + 1,
  1762.                                               $trailingStart $prefixEnd - 1
  1763.                 ));
  1764.                 $command array_shift($params);
  1765.                 // }
  1766.  
  1767.                 $ircdata->from = $prefix;
  1768.                 $ircdata->params = $params;
  1769.                 $ircdata->message = $trailing;
  1770.                 $ircdata->messageex = explode(' '$trailing);
  1771.  
  1772.                 // parse ident thingy
  1773.                 if (preg_match('/^(\S+)!(\S+)@(\S+)$/'$prefix$matches)) {
  1774.                     $ircdata->nick = $matches[1];
  1775.                     $ircdata->ident = $matches[2];
  1776.                     $ircdata->host = $matches[3];
  1777.                 else {
  1778.                     $ircdata->nick = '';
  1779.                     $ircdata->ident = '';
  1780.                     $ircdata->host = $prefix;
  1781.                 }
  1782.  
  1783.                 // figure out what SMARTIRC_TYPE this message is
  1784.                 switch ($command{
  1785.                     case SMARTIRC_RPL_WELCOME:
  1786.                     case SMARTIRC_RPL_YOURHOST:
  1787.                     case SMARTIRC_RPL_CREATED:
  1788.                     case SMARTIRC_RPL_MYINFO:
  1789.                     case SMARTIRC_RPL_BOUNCE:
  1790.                         $ircdata->type = SMARTIRC_TYPE_LOGIN;
  1791.                         break;
  1792.  
  1793.                     case SMARTIRC_RPL_LUSERCLIENT:
  1794.                     case SMARTIRC_RPL_LUSEROP:
  1795.                     case SMARTIRC_RPL_LUSERUNKNOWN:
  1796.                     case SMARTIRC_RPL_LUSERME:
  1797.                     case SMARTIRC_RPL_LUSERCHANNELS:
  1798.                         $ircdata->type = SMARTIRC_TYPE_INFO;
  1799.                         break;
  1800.  
  1801.                     case SMARTIRC_RPL_MOTDSTART:
  1802.                     case SMARTIRC_RPL_MOTD:
  1803.                     case SMARTIRC_RPL_ENDOFMOTD:
  1804.                         $ircdata->type = SMARTIRC_TYPE_MOTD;
  1805.                         break;
  1806.  
  1807.                     case SMARTIRC_RPL_NAMREPLY:
  1808.                         $ircdata->type = SMARTIRC_TYPE_NAME;
  1809.                         if ($params[0== $this->_nick):
  1810.                             $ircdata->channel = $params[2];
  1811.                         else:
  1812.                             $ircdata->channel = $params[1];
  1813.                         endif;
  1814.                         break;
  1815.  
  1816.                     case SMARTIRC_RPL_ENDOFNAMES:
  1817.                         $ircdata->type = SMARTIRC_TYPE_NAME;
  1818.                         if ($params[0== $this->_nick):
  1819.                             $ircdata->channel = $params[1];
  1820.                         else:
  1821.                             $ircdata->channel = $params[0];
  1822.                         endif;
  1823.                         break;
  1824.  
  1825.                     case SMARTIRC_RPL_WHOREPLY:
  1826.                     case SMARTIRC_RPL_ENDOFWHO:
  1827.                         $ircdata->type = SMARTIRC_TYPE_WHO;
  1828.                         if ($params[0== $this->_nick):
  1829.                             $ircdata->channel = $params[1];
  1830.                         else:
  1831.                             $ircdata->channel = $params[0];
  1832.                         endif;
  1833.                         break;
  1834.  
  1835.                     case SMARTIRC_RPL_LISTSTART:
  1836.                         $ircdata->type = SMARTIRC_TYPE_NONRELEVANT;
  1837.                         break;
  1838.  
  1839.                     case SMARTIRC_RPL_LIST:
  1840.                     case SMARTIRC_RPL_LISTEND:
  1841.                         $ircdata->type = SMARTIRC_TYPE_LIST;
  1842.                         break;
  1843.  
  1844.                     case SMARTIRC_RPL_BANLIST:
  1845.                     case SMARTIRC_RPL_ENDOFBANLIST:
  1846.                         $ircdata->type = SMARTIRC_TYPE_BANLIST;
  1847.                         $ircdata->channel = $params[0];
  1848.                         break;
  1849.  
  1850.                     case SMARTIRC_RPL_TOPIC:
  1851.                         $ircdata->type = SMARTIRC_TYPE_TOPIC;
  1852.                         $ircdata->channel = $params[0];
  1853.                         break;
  1854.  
  1855.                     case SMARTIRC_RPL_WHOISUSER:
  1856.                     case SMARTIRC_RPL_WHOISSERVER:
  1857.                     case SMARTIRC_RPL_WHOISOPERATOR:
  1858.                     case SMARTIRC_RPL_WHOISIDLE:
  1859.                     case SMARTIRC_RPL_ENDOFWHOIS:
  1860.                     case SMARTIRC_RPL_WHOISCHANNELS:
  1861.                         $ircdata->type = SMARTIRC_TYPE_WHOIS;
  1862.                         break;
  1863.  
  1864.                     case SMARTIRC_RPL_WHOWASUSER:
  1865.                     case SMARTIRC_RPL_ENDOFWHOWAS:
  1866.                         $ircdata->type = SMARTIRC_TYPE_WHOWAS;
  1867.                         break;
  1868.  
  1869.                     case SMARTIRC_RPL_UMODEIS:
  1870.                         $ircdata->type = SMARTIRC_TYPE_USERMODE;
  1871.                         break;
  1872.  
  1873.                     case SMARTIRC_RPL_CHANNELMODEIS:
  1874.                         $ircdata->type = SMARTIRC_TYPE_CHANNELMODE;
  1875.                         $ircdata->channel = $params[0];
  1876.                         break;
  1877.  
  1878.                     case SMARTIRC_ERR_NICKNAMEINUSE:
  1879.                     case SMARTIRC_ERR_NOTREGISTERED:
  1880.                         $ircdata->type = SMARTIRC_TYPE_ERROR;
  1881.                         break;
  1882.  
  1883.                     case 'PRIVMSG':
  1884.                         if (strspn($ircdata->params[0]'&#+!')) {
  1885.                             $ircdata->type = SMARTIRC_TYPE_CHANNEL;
  1886.                             $ircdata->channel = $params[0];
  1887.                             break;
  1888.                         }
  1889.                         if ($ircdata->message{0== chr(1)) {
  1890.                             if (preg_match("/^\1ACTION .*\1\$/"$ircdata->message)) {
  1891.                                 $ircdata->type = SMARTIRC_TYPE_ACTION;
  1892.                                 $ircdata->channel = $params[0];
  1893.                                 break;
  1894.                             }
  1895.                             if (preg_match("/^\1.*\1\$/"$ircdata->message)) {
  1896.                                 $ircdata->type = (SMARTIRC_TYPE_CTCP_REQUEST | SMARTIRC_TYPE_CTCP);
  1897.                                 break;
  1898.                             }
  1899.                         }
  1900.                         $ircdata->type = SMARTIRC_TYPE_QUERY;
  1901.                         break;
  1902.  
  1903.                     case 'NOTICE':
  1904.                         if (preg_match("/^\1.*\1\$/"$ircdata->message)) {
  1905.                             $ircdata->type = (SMARTIRC_TYPE_CTCP_REPLY | SMARTIRC_TYPE_CTCP);
  1906.                             break;
  1907.                         }
  1908.                         $ircdata->type = SMARTIRC_TYPE_NOTICE;
  1909.                         break;
  1910.  
  1911.                     case 'INVITE':
  1912.                         $ircdata->type = SMARTIRC_TYPE_INVITE;
  1913.                         break;
  1914.  
  1915.                     case 'JOIN':
  1916.                         $ircdata->type = SMARTIRC_TYPE_JOIN;
  1917.                         $ircdata->channel = (!empty($params[0])) $params[0$ircdata->message;
  1918.                         break;
  1919.  
  1920.                     case 'TOPIC':
  1921.                         $ircdata->type = SMARTIRC_TYPE_TOPICCHANGE;
  1922.                         $ircdata->channel = $params[0];
  1923.                         break;
  1924.  
  1925.                     case 'NICK':
  1926.                         $ircdata->type = SMARTIRC_TYPE_NICKCHANGE;
  1927.                         break;
  1928.  
  1929.                     case 'KICK':
  1930.                         $ircdata->type = SMARTIRC_TYPE_KICK;
  1931.                         $ircdata->channel = $params[0];
  1932.                         break;
  1933.  
  1934.                     case 'PART':
  1935.                         $ircdata->type = SMARTIRC_TYPE_PART;
  1936.                         $ircdata->channel = $params[0];
  1937.                         break;
  1938.  
  1939.                     case 'MODE':
  1940.                         $ircdata->type = SMARTIRC_TYPE_MODECHANGE;
  1941.                         $ircdata->channel = $params[0];
  1942.                         break;
  1943.  
  1944.                     case 'QUIT':
  1945.                         $ircdata->type = SMARTIRC_TYPE_QUIT;
  1946.                         break;
  1947.  
  1948.                     default:
  1949.                         $this->log(SMARTIRC_DEBUG_IRCMESSAGES'DEBUG_IRCMESSAGES: '
  1950.                             ."command type UNKNOWN ($command)",
  1951.                             __FILE____LINE__
  1952.                         );
  1953.                         $ircdata->type = SMARTIRC_TYPE_UNKNOWN;
  1954.                         break;
  1955.                 }
  1956.  
  1957.                 $this->log(SMARTIRC_DEBUG_MESSAGEPARSER'DEBUG_MESSAGEPARSER: '
  1958.                     .'ircdata nick:"'.$ircdata->nick
  1959.                     .'" ident:"'.$ircdata->ident
  1960.                     .'" host:"'.$ircdata->host
  1961.                     .'" type:"'.$ircdata->type
  1962.                     .'" from:"'.$ircdata->from
  1963.                     .'" channel:"'.$ircdata->channel
  1964.                     .'" message:"'.$ircdata->message.'"'__FILE____LINE__
  1965.                 );
  1966.  
  1967.                 // lets see if we have a messagehandler for it
  1968.                 if (is_numeric($command)) {
  1969.                     if (!array_key_exists($command$this->nreplycodes)) {
  1970.                         $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER,
  1971.                             'DEBUG_MESSAGEHANDLER: cannot translate unrecognized'
  1972.                             ." messagecode $command into a command type",
  1973.                             __FILE____LINE__
  1974.                         );
  1975.                         $methodname 'event_' $command;
  1976.                     else {
  1977.                         $methodname 'event_'.strtolower($this->nreplycodes[$command]);
  1978.                     }
  1979.  
  1980.                     $_methodname '_'.$methodname;
  1981.                     $_codetype 'by numeric';
  1982.                 else {
  1983.                     $methodname 'event_'.strtolower($command);
  1984.                     $_methodname '_'.$methodname;
  1985.                     $_codetype 'by string';
  1986.                 }
  1987.  
  1988.                 $found = false;
  1989.  
  1990.                 // if exists call internal method for the handling
  1991.                 if (method_exists($this$_methodname)) {
  1992.                     $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER'DEBUG_MESSAGEHANDLER: '
  1993.                         .'calling internal method "'.get_class($this).'->'
  1994.                         .$_methodname.'" ('.$_codetype.')'__FILE____LINE__
  1995.                     );
  1996.                     $this->$_methodname($ircdata);
  1997.                     $found = true;
  1998.                 }
  1999.  
  2000.                 // if exists call user defined method for the handling
  2001.                 if (method_exists($this$methodname)) {
  2002.                     $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER'DEBUG_MESSAGEHANDLER: '
  2003.                         .'calling user defined method "'.get_class($this).'->'
  2004.                         .$methodname.'" ('.$_codetype.')'__FILE____LINE__
  2005.                     );
  2006.                     $this->$methodname($ircdata);
  2007.                     $found = true;
  2008.                 }
  2009.  
  2010.                 if (!$found{
  2011.                     $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER'DEBUG_MESSAGEHANDLER: no'
  2012.                         .' method found for "'.$command.'" ('.$methodname.')',
  2013.                         __FILE____LINE__
  2014.                     );
  2015.                 }
  2016.  
  2017.                 // now the actionhandlers are coming
  2018.                 foreach ($this->_actionhandler as $i => $handlerinfo{
  2019.  
  2020.                     $hmsg $handlerinfo['message'];
  2021.                     $regex ($hmsg{0== $hmsg{strlen($hmsg- 1})
  2022.                         ? $hmsg
  2023.                         : '/' $hmsg '/';
  2024.  
  2025.                     if (($handlerinfo['type'$ircdata->type)
  2026.                         && preg_match($regex$ircdata->message)
  2027.                     {
  2028.                         $this->log(SMARTIRC_DEBUG_ACTIONHANDLER'DEBUG_ACTIONHANDLER: '
  2029.                             ."actionhandler match found for id: $i type: "
  2030.                             .$ircdata->type.' message: "'.$ircdata->message
  2031.                             ."\" regex: \"$regex\""__FILE____LINE__
  2032.                         );
  2033.  
  2034.                         $callback $handlerinfo['callback'];
  2035.  
  2036.                         $cbstring (is_array($callback))
  2037.                             ? (is_object($callback[0])
  2038.                                 ? get_class($callback[0])
  2039.                                 : $callback[0]
  2040.                               '->' $callback[1]
  2041.                             : '(anonymous function)';
  2042.  
  2043.                         if (is_callable($callback)) {
  2044.                             $this->log(SMARTIRC_DEBUG_ACTIONHANDLER,
  2045.                                 'DEBUG_ACTIONHANDLER: calling "'.$cbstring.'"',
  2046.                                 __FILE____LINE__
  2047.                             );
  2048.                             call_user_func($callback$this$ircdata);
  2049.                         else {
  2050.                             $this->log(SMARTIRC_DEBUG_ACTIONHANDLER,
  2051.                                 'DEBUG_ACTIONHANDLER: callback is invalid! "'.$cbstring.'"',
  2052.                                 __FILE____LINE__
  2053.                             );
  2054.                         }
  2055.                     }
  2056.                 }
  2057.  
  2058.                 unset($ircdata);
  2059.             }
  2060.         }
  2061.  
  2062.         // if we've done anything that didn't work and the connection is broken,
  2063.         // log it and fix it
  2064.         if ($this->_connectionerror{
  2065.             $this->log(SMARTIRC_DEBUG_CONNECTION'DEBUG_CONNECTION: connection'
  2066.                 .' error detected, attempting reconnect!'__FILE____LINE__
  2067.             );
  2068.             $this->reconnect();
  2069.         }
  2070.         return $this;
  2071.     }
  2072.  
  2073.     /**
  2074.      * waits for a special message type and returns the answer
  2075.      *
  2076.      * Creates a special actionhandler for that given TYPE and returns the answer.
  2077.      * This will only receive the requested type, immediately quit and disconnect from the IRC server.
  2078.      * Made for showing IRC statistics on your homepage, or other IRC related information.
  2079.      *
  2080.      * @api
  2081.      * @param integer $messagetype see in the documentation 'Message Types'
  2082.      * @param string  $regex the pattern to match on
  2083.      * @return array answer from the IRC server for this $messagetype
  2084.      */
  2085.     public function listenFor($messagetype$regex '.*')
  2086.     {
  2087.         $listenfor = new Net_SmartIRC_listenfor();
  2088.         $this->registerActionHandler($messagetype$regexarray($listenfor'handler'));
  2089.         $this->listen();
  2090.         return $listenfor->result;
  2091.     }
  2092.  
  2093.     /**
  2094.      * registers a new actionhandler and returns the assigned id
  2095.      *
  2096.      * Registers an actionhandler in Net_SmartIRC for calling it later.
  2097.      * The actionhandler id is needed for unregistering the actionhandler.
  2098.      *
  2099.      * @api
  2100.      * @see example.php
  2101.      * @param integer $handlertype bits constants, see in this documentation Message Types
  2102.      * @param string $regexhandler the message that has to be in the IRC message in regex syntax
  2103.      * @param object|callable$object either an object with the method, or a callable
  2104.      * @param string $methodname the methodname that will be called when the handler happens
  2105.      * @return integer assigned actionhandler id
  2106.      */
  2107.     public function registerActionHandler($handlertype$regexhandler$object,
  2108.         $methodname ''
  2109.     {
  2110.         // precheck
  2111.         if (!($handlertype SMARTIRC_TYPE_ALL)) {
  2112.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: passed invalid handler'
  2113.                 .'type to registerActionHandler()'__FILE____LINE__
  2114.             );
  2115.             return false;
  2116.         }
  2117.  
  2118.         if (!empty($methodname)) {
  2119.             $object = array($object$methodname);
  2120.         }
  2121.  
  2122.         $id $this->_actionhandlerid++;
  2123.         $this->_actionhandler[= array(
  2124.             'id' => $id,
  2125.             'type' => $handlertype,
  2126.             'message' => $regexhandler,
  2127.             'callback' => $object,
  2128.         );
  2129.         $this->log(SMARTIRC_DEBUG_ACTIONHANDLER'DEBUG_ACTIONHANDLER: '
  2130.             .'actionhandler('.$id.') registered'__FILE____LINE__
  2131.         );
  2132.         return $id;
  2133.     }
  2134.  
  2135.     /**
  2136.      * unregisters an existing actionhandler
  2137.      *
  2138.      * @api
  2139.      * @param integer $handlertype 
  2140.      * @param string $regexhandler 
  2141.      * @param object $object 
  2142.      * @param string $methodname 
  2143.      * @return boolean 
  2144.      */
  2145.     public function unregisterActionHandler($handlertype$regexhandler,
  2146.         $object$methodname ''
  2147.     {
  2148.         // precheck
  2149.         if (!($handlertype SMARTIRC_TYPE_ALL)) {
  2150.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING: passed invalid handler'
  2151.                 .'type to unregisterActionHandler()'__FILE____LINE__
  2152.             );
  2153.             return false;
  2154.         }
  2155.  
  2156.         if (!empty($methodname)) {
  2157.             $object = array($object$methodname);
  2158.         }
  2159.  
  2160.         foreach ($this->_actionhandler as $i => &$handlerinfo{
  2161.             if ($handlerinfo['type'== $handlertype
  2162.                 && $handlerinfo['message'== $regexhandler
  2163.                 && $handlerinfo['callback'== $object
  2164.             {
  2165.                 $id $handlerinfo['id'];
  2166.                 unset($this->_actionhandler[$i]);
  2167.  
  2168.                 $this->log(SMARTIRC_DEBUG_ACTIONHANDLER'DEBUG_ACTIONHANDLER: '
  2169.                     .'actionhandler('.$id.') unregistered'__FILE____LINE__
  2170.                 );
  2171.                 $this->_actionhandler = array_values($this->_actionhandler);
  2172.                 return $this;
  2173.             }
  2174.         }
  2175.  
  2176.         $this->log(SMARTIRC_DEBUG_ACTIONHANDLER'DEBUG_ACTIONHANDLER: could '
  2177.             .'not find actionhandler type: "'.$handlertype.'" message: "'
  2178.             .$regexhandler.'" matching callback. Nothing unregistered'__FILE____LINE__
  2179.         );
  2180.         return false;
  2181.     }
  2182.  
  2183.     /**
  2184.      * unregisters an existing actionhandler via the id
  2185.      *
  2186.      * @api
  2187.      * @param integer|array$id 
  2188.      * @return boolean|void
  2189.      */
  2190.     public function unregisterActionId($id)
  2191.     {
  2192.         if (is_array($id)) {
  2193.             foreach ($id as $each{
  2194.                 $this->unregisterActionId($each);
  2195.             }
  2196.             return $this;
  2197.         }
  2198.  
  2199.         foreach ($this->_actionhandler as $i => &$handlerinfo{
  2200.             if ($handlerinfo['id'== $id{
  2201.                 unset($this->_actionhandler[$i]);
  2202.  
  2203.                 $this->log(SMARTIRC_DEBUG_ACTIONHANDLER'DEBUG_ACTIONHANDLER: '
  2204.                     .'actionhandler('.$id.') unregistered'__FILE____LINE__
  2205.                 );
  2206.                 $this->_actionhandler = array_values($this->_actionhandler);
  2207.                 return $this;
  2208.             }
  2209.         }
  2210.  
  2211.         $this->log(SMARTIRC_DEBUG_ACTIONHANDLER'DEBUG_ACTIONHANDLER: could '
  2212.             .'not find actionhandler id: '.$id.' _not_ unregistered',
  2213.             __FILE____LINE__
  2214.         );
  2215.         return false;
  2216.     }
  2217.  
  2218.     /**
  2219.      * registers a timehandler and returns the assigned id
  2220.      *
  2221.      * Registers a timehandler in Net_SmartIRC, which will be called in the specified interval.
  2222.      * The timehandler id is needed for unregistering the timehandler.
  2223.      *
  2224.      * @api
  2225.      * @see example7.php
  2226.      * @param integer $interval interval time in milliseconds
  2227.      * @param object|callable$object either an object with the method, or a callable
  2228.      * @param string $methodname the methodname that will be called when the handler happens
  2229.      * @return integer assigned timehandler id
  2230.      */
  2231.     public function registerTimeHandler($interval$object$methodname '')
  2232.     {
  2233.         $id $this->_timehandlerid++;
  2234.  
  2235.         if (!empty($methodname)) {
  2236.             $object = array($object$methodname);
  2237.         }
  2238.  
  2239.         $this->_timehandler[= array(
  2240.             'id' => $id,
  2241.             'interval' => $interval,
  2242.             'callback' => $object,
  2243.             'lastmicrotimestamp' => microtime(true),
  2244.         );
  2245.         $this->log(SMARTIRC_DEBUG_TIMEHANDLER'DEBUG_TIMEHANDLER: timehandler('
  2246.             .$id.') registered'__FILE____LINE__
  2247.         );
  2248.  
  2249.         if (($this->_mintimer == false|| ($interval $this->_mintimer)) {
  2250.             $this->_mintimer = $interval;
  2251.         }
  2252.  
  2253.         return $id;
  2254.     }
  2255.  
  2256.     /**
  2257.      * unregisters an existing timehandler via the id
  2258.      *
  2259.      * @api
  2260.      * @see example7.php
  2261.      * @param integer $id 
  2262.      * @return boolean 
  2263.      */
  2264.     public function unregisterTimeId($id)
  2265.     {
  2266.         if (is_array($id)) {
  2267.             foreach ($id as $each{
  2268.                 $this->unregisterTimeId($each);
  2269.             }
  2270.             return $this;
  2271.         }
  2272.  
  2273.         foreach ($this->_timehandler as $i => &$handlerinfo{
  2274.             if ($handlerinfo['id'== $id{
  2275.                 unset($this->_timehandler[$i]);
  2276.  
  2277.                 $this->log(SMARTIRC_DEBUG_TIMEHANDLER'DEBUG_TIMEHANDLER: '
  2278.                     .'timehandler('.$id.') unregistered'__FILE____LINE__
  2279.                 );
  2280.                 $this->_timehandler = array_values($this->_timehandler);
  2281.  
  2282.                 $timerarray = array();
  2283.                 foreach ($this->_timehandler as $values{
  2284.                     $timerarray[$values->interval;
  2285.                 }
  2286.  
  2287.                 $this->_mintimer = (
  2288.                     array_multisort($timerarraySORT_NUMERICSORT_ASC)
  2289.                     && isset($timerarray[0])
  2290.                 $timerarray[0]
  2291.                     : false;
  2292.  
  2293.                 return $this;
  2294.             }
  2295.         }
  2296.  
  2297.         $this->log(SMARTIRC_DEBUG_TIMEHANDLER'DEBUG_TIMEHANDLER: could not '
  2298.             ."find timehandler id: $id _not_ unregistered",
  2299.             __FILE____LINE__
  2300.         );
  2301.         return false;
  2302.     }
  2303.  
  2304.     /**
  2305.      * loads a module using preset path and given name
  2306.      *
  2307.      * @api
  2308.      * @param string $name 
  2309.      * @return boolean|Net_SmartIRC
  2310.      */
  2311.     public function loadModule($name)
  2312.     {
  2313.         // is the module already loaded?
  2314.         if (isset($this->_modules[$name])) {
  2315.             $this->log(SMARTIRC_DEBUG_NOTICE'WARNING! module with the name "'
  2316.                 .$name.'" already loaded!'__FILE____LINE__
  2317.             );
  2318.             return false;
  2319.         }
  2320.  
  2321.         $classname = "Net_SmartIRC_module_$name";
  2322.         if (class_exists($classname)) {
  2323.             $this->log(SMARTIRC_DEBUG_MODULES"DEBUG_MODULES: \"$name\" module class"
  2324.                 .' exists, initializing...'__FILE____LINE__
  2325.             );
  2326.         else {
  2327.             $filename $this->_modulepath."/$name.php";
  2328.             if (!file_exists($filename)) {
  2329.                 $this->log(SMARTIRC_DEBUG_MODULES"DEBUG_MODULES: couldn't load "
  2330.                     ."module; file \"$filename\" doesn't exist"__FILE____LINE__
  2331.                 );
  2332.                 return false;
  2333.             }
  2334.             // pray that there is no parse error, it will kill us!
  2335.             include_once($filename);
  2336.  
  2337.             if (!class_exists($classname)) {
  2338.                 $this->log(SMARTIRC_DEBUG_MODULES"DEBUG_MODULES: class $classname"
  2339.                     ." not found in $filename, aborting..."__FILE____LINE__
  2340.                 );
  2341.                 return false;
  2342.             }
  2343.  
  2344.             $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: loading module '
  2345.                 ."\"$name\" from file..."__FILE____LINE__
  2346.             );
  2347.         }
  2348.  
  2349.         $methods array_flip(get_class_methods($classname));
  2350.  
  2351.         if (!(isset($methods['__construct']|| isset($methods['module_init']))) {
  2352.             $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: required method '
  2353.                 .$classname.'::__construct() not found, aborting...',
  2354.                 __FILE____LINE__
  2355.             );
  2356.             return false;
  2357.         }
  2358.  
  2359.         if (!(isset($methods['__destruct']|| isset($methods['module_exit']))) {
  2360.             $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: required method '
  2361.                 .$classname.'::__destruct() not found, aborting...',
  2362.                 __FILE____LINE__
  2363.             );
  2364.             return false;
  2365.         }
  2366.  
  2367.         $vars get_class_vars($classname);
  2368.         $required = array('name''description''author''license');
  2369.  
  2370.         foreach ($required as $varname{
  2371.             if (!isset($vars[$varname])) {
  2372.                 $this->log(SMARTIRC_DEBUG_NOTICE'NOTICE: required module'
  2373.                     ."property {$classname}::\${$varname} not found.",
  2374.                     __FILE____LINE__
  2375.                 );
  2376.             }
  2377.         }
  2378.  
  2379.         // looks like the module satisfies us, so instantiate it
  2380.         if (isset($methods['module_init'])) {
  2381.             // we're using an old module_init style module
  2382.             $this->_modules[$name= new $classname;
  2383.             $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: calling '
  2384.                 .$classname.'::module_init()'__FILE____LINE__
  2385.             );
  2386.             $this->_modules[$name]->module_init($this);
  2387.         else if (func_num_args(== 1{
  2388.             // we're using a new __construct style module, which maintains its
  2389.             // own reference to the $irc client object it's being used on
  2390.             $this->_modules[$name= new $classname($this);
  2391.         else
  2392.         // we're using new style AND we have args to pass to the constructor
  2393.         if (func_num_args(== 2{
  2394.             // only one arg, so pass it as is
  2395.             $this->_modules[$name= new $classname($thisfunc_get_arg(1));
  2396.         else {
  2397.             // multiple args, so pass them in an array
  2398.             $this->_modules[$name= new $classname($thisarray_slice(func_get_args()1));
  2399.         }
  2400.  
  2401.         $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: successfully loaded'
  2402.             ." module: $name"__FILE____LINE__
  2403.         );
  2404.         return $this;
  2405.     }
  2406.  
  2407.     /**
  2408.      * unloads a module by the name originally loaded with
  2409.      *
  2410.      * @api
  2411.      * @param string $name 
  2412.      * @return boolean|Net_SmartIRC
  2413.      */
  2414.     public function unloadModule($name)
  2415.     {
  2416.         $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: unloading module: '
  2417.             ."$name..."__FILE____LINE__
  2418.         );
  2419.  
  2420.         if (isset($this->_modules[$name])) {
  2421.             if (in_array('module_exit',
  2422.                     get_class_methods(get_class($this->_modules[$name]))
  2423.             )) {
  2424.                 $this->_modules[$name]->module_exit($this);
  2425.             }
  2426.  
  2427.             unset($this->_modules[$name]);
  2428.             $this->log(SMARTIRC_DEBUG_MODULES'DEBUG_MODULES: successfully'
  2429.                 ." unloaded module: $name"__FILE____LINE__);
  2430.             return $this;
  2431.         }
  2432.  
  2433.         $this->log(SMARTIRC_DEBUG_MODULES"DEBUG_MODULES: couldn't unload"
  2434.             ." module: $name (it's not loaded!)"__FILE____LINE__
  2435.         );
  2436.         return false;
  2437.     }
  2438.  
  2439.     /**
  2440.      * Returns an array of the module names that are currently loaded
  2441.      *
  2442.      * @api
  2443.      * @return array 
  2444.      */
  2445.     public function loadedModules()
  2446.     {
  2447.         return array_keys($this->_modules);
  2448.     }
  2449.  
  2450.     // <protected methods>
  2451.     /**
  2452.      * adds an user to the channelobject or updates his info
  2453.      *
  2454.      * @internal
  2455.      * @param object $channel 
  2456.      * @param object $newuser 
  2457.      * @return Net_SmartIRC 
  2458.      */
  2459.     protected function _adduser(&$channel&$newuser)
  2460.     {
  2461.         $lowerednick strtolower($newuser->nick);
  2462.         if ($this->isJoined($channel->name$newuser->nick)) {
  2463.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING'DEBUG_CHANNELSYNCING: '
  2464.                 .'updating user: '.$newuser->nick.' on channel: '
  2465.                 .$channel->name__FILE____LINE__
  2466.             );
  2467.  
  2468.             // lets update the existing user
  2469.             $currentuser &$channel->users[$lowerednick];
  2470.  
  2471.             $props = array('ident''host''realname''ircop''founder',
  2472.                 'admin''op''hop''voice''away''server''hopcount'
  2473.             );
  2474.             foreach ($props as $prop{
  2475.                 if ($newuser->$prop !== null{
  2476.                     $currentuser->$prop $newuser->$prop;
  2477.                 }
  2478.             }
  2479.         else {
  2480.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING'DEBUG_CHANNELSYNCING: '
  2481.                 .'adding user: '.$newuser->nick.' to channel: '.$channel->name,
  2482.                 __FILE____LINE__
  2483.             );
  2484.  
  2485.             $channel->users[$lowerednick$newuser;
  2486.         }
  2487.  
  2488.         $user &$channel->users[$lowerednick];
  2489.         $modes = array('founder''admin''op''hop''voice');
  2490.  
  2491.         foreach ($modes as $mode{
  2492.             if ($user->$mode{
  2493.                 $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2494.                     "DEBUG_CHANNELSYNCING: adding $mode".$user->nick
  2495.                     .' to channel: '.$channel->name__FILE____LINE__
  2496.                 );
  2497.                 $ms $mode.'s';
  2498.                 $channel->{$ms}[$user->nick= true;
  2499.             }
  2500.         }
  2501.         return $this;
  2502.     }
  2503.  
  2504.     /**
  2505.      * looks for any time handlers that have timed out and calls them if valid
  2506.      *
  2507.      * @internal
  2508.      * @return void 
  2509.      */
  2510.     protected function _callTimeHandlers()
  2511.     {
  2512.         foreach ($this->_timehandler as &$handlerinfo{
  2513.             $microtimestamp microtime(true);
  2514.             if ($microtimestamp >= $handlerinfo['lastmicrotimestamp']
  2515.                 + ($handlerinfo['interval'/ 1000.0)
  2516.             {
  2517.                 $callback $handlerinfo['callback'];
  2518.                 $handlerinfo['lastmicrotimestamp'$microtimestamp;
  2519.  
  2520.                 $cbstring (is_array($callback))
  2521.                     ? (is_object($callback[0])
  2522.                         ? get_class($callback[0])
  2523.                         : $callback[0]
  2524.                       '->' $callback[1]
  2525.                     : '(anonymous function)';
  2526.  
  2527.                 if (is_callable($callback)) {
  2528.                     $this->log(SMARTIRC_DEBUG_TIMEHANDLER'DEBUG_TIMEHANDLER: calling "'.$cbstring.'"',
  2529.                         __FILE____LINE__
  2530.                     );
  2531.                     call_user_func($callback$this);
  2532.                 else {
  2533.                     $this->log(SMARTIRC_DEBUG_TIMEHANDLER,
  2534.                         'DEBUG_TIMEHANDLER: callback is invalid! "'.$cbstring.'"',
  2535.                         __FILE____LINE__
  2536.                     );
  2537.                 }
  2538.             }
  2539.         }
  2540.     }
  2541.  
  2542.     /**
  2543.      * An active-pinging system to keep the bot from dropping the connection
  2544.      *
  2545.      * @internal
  2546.      * @return void 
  2547.      */
  2548.     protected function _pingcheck()
  2549.     {
  2550.         $time time();
  2551.         if ($time $this->_lastrx > $this->_rxtimeout{
  2552.             $this->reconnect();
  2553.             $this->_lastrx = $time;
  2554.         elseif ($time $this->_lastrx > $this->_rxtimeout/2{
  2555.             $this->send('PING '.$this->_addressSMARTIRC_CRITICAL);
  2556.         }
  2557.     }
  2558.  
  2559.     /**
  2560.      * sends a raw message to the IRC server
  2561.      *
  2562.      * Don't use this directly! Use message() or send() instead.
  2563.      *
  2564.      * @internal
  2565.      * @param string $data 
  2566.      * @return boolean 
  2567.      */
  2568.     protected function _rawsend($data)
  2569.     {
  2570.         if ($this->_updatestate(!= SMARTIRC_STATE_CONNECTED{
  2571.             return false;
  2572.         }
  2573.  
  2574.         $this->log(SMARTIRC_DEBUG_IRCMESSAGES'DEBUG_IRCMESSAGES: sent: "'
  2575.             .$data.'"'__FILE____LINE__
  2576.         );
  2577.  
  2578.         $result fwrite($this->_socket$data.SMARTIRC_CRLF);
  2579.  
  2580.         if (!$result{
  2581.             // writing to the socket failed, means the connection is broken
  2582.             $this->_connectionerror = true;
  2583.         else {
  2584.             $this->_lasttx = time();
  2585.         }
  2586.  
  2587.         return $result;
  2588.     }
  2589.  
  2590.     /**
  2591.      * removes an user from one channel or all if he quits
  2592.      *
  2593.      * @internal
  2594.      * @param object $ircdata 
  2595.      * @return Net_SmartIRC 
  2596.      */
  2597.     protected function _removeuser($ircdata)
  2598.     {
  2599.         if ($ircdata->type (SMARTIRC_TYPE_PART | SMARTIRC_TYPE_QUIT)) {
  2600.             $nick $ircdata->nick;
  2601.         else if ($ircdata->type SMARTIRC_TYPE_KICK{
  2602.             $nick $ircdata->params[1];
  2603.         else {
  2604.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING'DEBUG_CHANNELSYNCING: '
  2605.                 .'unknown TYPE ('.$ircdata->type
  2606.                 .') in _removeuser(), trying default'__FILE____LINE__
  2607.             );
  2608.             $nick $ircdata->nick;
  2609.         }
  2610.  
  2611.         $lowerednick strtolower($nick);
  2612.  
  2613.         if ($this->_nick == $nick{
  2614.             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2615.                 'DEBUG_CHANNELSYNCING: we left channel: '.$ircdata->channel
  2616.                 .' destroying...'__FILE____LINE__
  2617.             );
  2618.             unset($this->_channels[strtolower($ircdata->channel)]);
  2619.         else {
  2620.             $lists = array('founders''admins''ops''hops''voices');
  2621.  
  2622.             if ($ircdata->type SMARTIRC_TYPE_QUIT{
  2623.                 $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2624.                     'DEBUG_CHANNELSYNCING: user '.$nick
  2625.                     .' quit, removing him from all channels'__FILE____LINE__
  2626.                 );
  2627.  
  2628.                 // remove the user from all channels
  2629.                 $channelkeys array_keys($this->_channels);
  2630.                 foreach ($channelkeys as $channelkey{
  2631.                     // loop through all channels
  2632.                     $channel &$this->getChannel($channelkey);
  2633.                     foreach ($channel->users as $uservalue{
  2634.                         // loop through all user in this channel
  2635.                         if ($nick == $uservalue->nick{
  2636.                             // found him, kill him
  2637.                             $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2638.                                 'DEBUG_CHANNELSYNCING: found him on channel: '
  2639.                                 .$channel->name.' destroying...',
  2640.                                 __FILE____LINE__
  2641.                             );
  2642.                             unset($channel->users[$lowerednick]);
  2643.  
  2644.                             foreach ($lists as $list{
  2645.                                 if (isset($channel->{$list}[$nick])) {
  2646.                                     // die!
  2647.                                     $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2648.                                         'DEBUG_CHANNELSYNCING: removing him '
  2649.                                         ."from $list list"__FILE____LINE__
  2650.                                     );
  2651.                                     unset($channel->{$list}[$nick]);
  2652.                                 }
  2653.                             }
  2654.                         }
  2655.                     }
  2656.                 }
  2657.             else {
  2658.                 $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2659.                     'DEBUG_CHANNELSYNCING: removing user: '.$nick
  2660.                     .' from channel: '.$ircdata->channel__FILE____LINE__
  2661.                 );
  2662.                 $channel &$this->getChannel($ircdata->channel);
  2663.                 unset($channel->users[$lowerednick]);
  2664.  
  2665.                 foreach ($lists as $list{
  2666.                     if (isset($channel->{$list}[$nick])) {
  2667.                         $this->log(SMARTIRC_DEBUG_CHANNELSYNCING,
  2668.                             'DEBUG_CHANNELSYNCING: removing him '
  2669.                             ."from $list list"__FILE____LINE__
  2670.                         );
  2671.                         unset($channel->{$list}[$nick]);
  2672.                     }
  2673.                 }
  2674.             }
  2675.         }
  2676.         return $this;
  2677.     }
  2678.  
  2679.     /**
  2680.      * updates and returns the current connection state
  2681.      *
  2682.      * @internal
  2683.      * @return boolean 
  2684.      */
  2685.     protected function _updatestate()
  2686.     {
  2687.         if (is_resource($this->_socket)) {
  2688.             $rtype get_resource_type($this->_socket);
  2689.             if ($this->_socket !== false
  2690.                 && (strtolower($rtype== 'socket' || $rtype == 'stream')
  2691.             {
  2692.                 $this->_state = SMARTIRC_STATE_CONNECTED;
  2693.             }
  2694.         else {
  2695.             $this->_state = SMARTIRC_STATE_DISCONNECTED;
  2696.             $this->_loggedin = false;
  2697.         }
  2698.  
  2699.         return $this->_state;
  2700.     }
  2701.  
  2702.     public function isError($object// is this even needed/used?
  2703.     {
  2704.         return (is_object($object)
  2705.             && strtolower(get_class($object)) == 'net_smartirc_error'
  2706.         );
  2707.     }
  2708.  
  2709.     protected function throwError($message)
  2710.     {
  2711.         return new Net_SmartIRC_Error($message);
  2712.     }
  2713. }
  2714.  
  2715. /**
  2716.  * Struct for parsed incoming messages
  2717.  */
  2718. class Net_SmartIRC_data
  2719. {
  2720.     /**
  2721.      * @var string 
  2722.      */
  2723.     public $from;
  2724.  
  2725.     /**
  2726.      * @var string 
  2727.      */
  2728.     public $nick;
  2729.  
  2730.     /**
  2731.      * @var string 
  2732.      */
  2733.     public $ident;
  2734.  
  2735.     /**
  2736.      * @var string 
  2737.      */
  2738.     public $host;
  2739.  
  2740.     /**
  2741.      * @var string 
  2742.      */
  2743.     public $channel;
  2744.  
  2745.     /**
  2746.      * @var array 
  2747.      */
  2748.     public $params = array();
  2749.  
  2750.     /**
  2751.      * @var string 
  2752.      */
  2753.     public $message;
  2754.  
  2755.     /**
  2756.      * @var array 
  2757.      */
  2758.     public $messageex = array();
  2759.  
  2760.     /**
  2761.      * @var integer 
  2762.      */
  2763.     public $type;
  2764.  
  2765.     /**
  2766.      * @var string 
  2767.      */
  2768.     public $rawmessage;
  2769.  
  2770.     /**
  2771.      * @var array 
  2772.      */
  2773.     public $rawmessageex = array();
  2774. }
  2775.  
  2776. /**
  2777.  * Struct for individual channel data
  2778.  */
  2779. class Net_SmartIRC_channel
  2780. {
  2781.     /**
  2782.      * @var string 
  2783.      */
  2784.     public $name;
  2785.  
  2786.     /**
  2787.      * @var string 
  2788.      */
  2789.     public $key;
  2790.  
  2791.     /**
  2792.      * @var array 
  2793.      */
  2794.     public $users = array();
  2795.  
  2796.     /**
  2797.      * @var array 
  2798.      */
  2799.     public $founders = array();
  2800.  
  2801.     /**
  2802.      * @var array 
  2803.      */
  2804.     public $admins = array();
  2805.  
  2806.     /**
  2807.      * @var array 
  2808.      */
  2809.     public $ops = array();
  2810.  
  2811.     /**
  2812.      * @var array 
  2813.      */
  2814.     public $hops = array();
  2815.  
  2816.     /**
  2817.      * @var array 
  2818.      */
  2819.     public $voices = array();
  2820.  
  2821.     /**
  2822.      * @var array 
  2823.      */
  2824.     public $bans = array();
  2825.  
  2826.     /**
  2827.      * @var string 
  2828.      */
  2829.     public $topic;
  2830.  
  2831.     /**
  2832.      * @var string 
  2833.      */
  2834.     public $user_limit = false;
  2835.  
  2836.     /**
  2837.      * @var string 
  2838.      */
  2839.     public $mode;
  2840.  
  2841.     /**
  2842.      * @var integer 
  2843.      */
  2844.     public $synctime_start = 0;
  2845.  
  2846.     /**
  2847.      * @var integer 
  2848.      */
  2849.     public $synctime_stop = 0;
  2850.  
  2851.     /**
  2852.      * @var integer 
  2853.      */
  2854.     public $synctime;
  2855. }
  2856.  
  2857. /**
  2858.  * Struct for individual user data
  2859.  */
  2860. class Net_SmartIRC_user
  2861. {
  2862.     /**
  2863.      * @var string 
  2864.      */
  2865.     public $nick;
  2866.  
  2867.     /**
  2868.      * @var string 
  2869.      */
  2870.     public $ident;
  2871.  
  2872.     /**
  2873.      * @var string 
  2874.      */
  2875.     public $host;
  2876.  
  2877.     /**
  2878.      * @var string 
  2879.      */
  2880.     public $realname;
  2881.  
  2882.     /**
  2883.      * @var boolean 
  2884.      */
  2885.     public $ircop;
  2886.  
  2887.     /**
  2888.      * @var boolean 
  2889.      */
  2890.     public $away;
  2891.  
  2892.     /**
  2893.      * @var string 
  2894.      */
  2895.     public $server;
  2896.  
  2897.     /**
  2898.      * @var integer 
  2899.      */
  2900.     public $hopcount;
  2901. }
  2902.  
  2903. /**
  2904.  * Struct for extra data that applies to each user in each channel they're in
  2905.  */
  2906. class Net_SmartIRC_channeluser extends Net_SmartIRC_user
  2907. {
  2908.     /**
  2909.      * @var boolean 
  2910.      */
  2911.     public $founder;
  2912.  
  2913.     /**
  2914.      * @var boolean 
  2915.      */
  2916.     public $admin;
  2917.  
  2918.     /**
  2919.      * @var boolean 
  2920.      */
  2921.     public $op;
  2922.  
  2923.     /**
  2924.      * @var boolean 
  2925.      */
  2926.     public $hop;
  2927.  
  2928.     /**
  2929.      * @var boolean 
  2930.      */
  2931.     public $voice;
  2932. }
  2933.  
  2934. /**
  2935.  * Struct for data that applies to each user server-wide
  2936.  */
  2937. class Net_SmartIRC_ircuser extends Net_SmartIRC_user
  2938. {
  2939.     /**
  2940.      * @var array 
  2941.      */
  2942.     public $joinedchannels = array();
  2943. }
  2944.  
  2945. /**
  2946.  * Built-in bot used by Net_SmartIRC::listenFor()
  2947.  */
  2948. class Net_SmartIRC_listenfor
  2949. {
  2950.     /**
  2951.      * @var array 
  2952.      */
  2953.     public $result = array();
  2954.  
  2955.     /**
  2956.      * stores the received answer into the result array
  2957.      *
  2958.      * @api
  2959.      * @param object $irc 
  2960.      * @param object $ircdata 
  2961.      * @return void 
  2962.      */
  2963.     public function handler(&$irc&$ircdata)
  2964.     {
  2965.         $irc->log(SMARTIRC_DEBUG_ACTIONHANDLER,
  2966.             'DEBUG_ACTIONHANDLER: listenfor handler called'__FILE____LINE__
  2967.         );
  2968.         $this->result[$ircdata;
  2969.         $irc->disconnect();
  2970.     }
  2971. }
  2972.  
  2973. class Net_SmartIRC_Error
  2974. {
  2975.     private $error_msg;
  2976.  
  2977.     public function __construct($message)
  2978.     {
  2979.         $this->error_msg $message;
  2980.     }
  2981.  
  2982.     public function getMessage()
  2983.     {
  2984.         return $this->error_msg;
  2985.     }
  2986. }

Documentation generated on Thu, 25 Jul 2019 12:49:09 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.