PageRenderTime 50ms CodeModel.GetById 14ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/php/Net/SmartIRC.php

https://bitbucket.org/adarshj/convenient_website
PHP | 2553 lines | 1236 code | 280 blank | 1037 comment | 297 complexity | 515caf13f9bffc1ea2efc42a31d06753 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * $Id: SmartIRC.php,v 1.54.2.14 2005/05/27 23:40:09 meebey Exp $
   4 * $Revision: 1.54.2.14 $
   5 * $Author: meebey $
   6 * $Date: 2005/05/27 23:40:09 $
   7 *
   8 * Net_SmartIRC
   9 * This is a PHP class for communication with IRC networks,
  10 * which conforms to the RFC 2812 (IRC protocol).
  11 * It's an API that handles all IRC protocol messages.
  12 * This class is designed for creating IRC bots, chats and show irc related info on webpages.
  13 *
  14 * Documenation, a HOWTO and examples are in SmartIRC included.
  15 *
  16 * Here you will find a service bot which I am also developing
  17 * <http://cvs.meebey.net/atbs> and <http://cvs.meebey.net/phpbitch>
  18 * Latest versions of Net_SmartIRC you will find on the project homepage
  19 * or get it through PEAR since SmartIRC is an official PEAR package.
  20 * See <http://pear.php.net/Net_SmartIRC>.
  21 *
  22 * Official Projet Homepage: <http://sf.net/projects/phpsmartirc>
  23 *
  24 * Net_SmartIRC conforms to RFC 2812 (Internet Relay Chat: Client Protocol)
  25 * 
  26 * Copyright (c) 2002-2003 Mirco 'meebey' Bauer <meebey@meebey.net> <http://www.meebey.net>
  27 * 
  28 * Full LGPL License: <http://www.gnu.org/licenses/lgpl.txt>
  29 * 
  30 * This library is free software; you can redistribute it and/or
  31 * modify it under the terms of the GNU Lesser General Public
  32 * License as published by the Free Software Foundation; either
  33 * version 2.1 of the License, or (at your option) any later version.
  34 *
  35 * This library is distributed in the hope that it will be useful,
  36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  38 * Lesser General Public License for more details.
  39 *
  40 * You should have received a copy of the GNU Lesser General Public
  41 * License along with this library; if not, write to the Free Software
  42 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  43 *
  44 */
  45// ------- PHP code ----------
  46include_once('SmartIRC/defines.php');
  47include_once('SmartIRC/irccommands.php');
  48include_once('SmartIRC/messagehandler.php');
  49define('SMARTIRC_VERSION', '1.0.0 ($Revision: 1.54.2.14 $)');
  50define('SMARTIRC_VERSIONSTRING', 'Net_SmartIRC '.SMARTIRC_VERSION);
  51
  52/**
  53 * main SmartIRC class
  54 *
  55 * @package Net_SmartIRC
  56 * @version 0.5.5
  57 * @author Mirco 'meebey' Bauer <mail@meebey.net>
  58 * @access public
  59 */
  60class Net_SmartIRC_base
  61{
  62    /**
  63     * @var resource
  64     * @access private
  65     */
  66    var $_socket;
  67    
  68    /**
  69     * @var string
  70     * @access private
  71     */
  72    var $_address;
  73    
  74    /**
  75     * @var integer
  76     * @access private
  77     */
  78    var $_port;
  79    
  80    /**
  81     * @var string
  82     * @access private
  83     */
  84    var $_nick;
  85    
  86    /**
  87     * @var string
  88     * @access private
  89     */
  90    var $_username;
  91    
  92    /**
  93     * @var string
  94     * @access private
  95     */
  96    var $_realname;
  97    
  98    /**
  99     * @var string
 100     * @access private
 101     */
 102    var $_usermode;
 103    
 104    /**
 105     * @var string
 106     * @access private
 107     */
 108    var $_password;
 109    
 110    /**
 111     * @var boolean
 112     * @access private
 113     */
 114    var $_state = false;
 115    
 116    /**
 117     * @var array
 118     * @access private
 119     */
 120    var $_actionhandler = array();
 121    
 122    /**
 123     * @var array
 124     * @access private
 125     */
 126    var $_timehandler = array();
 127    
 128    /**
 129     * @var integer
 130     * @access private
 131     */
 132    var $_debug = SMARTIRC_DEBUG_NOTICE;
 133    
 134    /**
 135     * @var array
 136     * @access private
 137     */
 138    var $_messagebuffer = array();
 139    
 140    /**
 141     * @var integer
 142     * @access private
 143     */
 144    var $_messagebuffersize;
 145    
 146    /**
 147     * @var boolean
 148     * @access private
 149     */
 150    var $_usesockets = false;
 151    
 152    /**
 153     * @var integer
 154     * @access private
 155     */
 156    var $_receivedelay = 100;
 157    
 158    /**
 159     * @var integer
 160     * @access private
 161     */
 162    var $_senddelay = 250;
 163    
 164    /**
 165     * @var integer
 166     * @access private
 167     */
 168    var $_logdestination = SMARTIRC_STDOUT;
 169    
 170    /**
 171     * @var resource
 172     * @access private
 173     */
 174    var $_logfilefp = 0;
 175    
 176    /**
 177     * @var string
 178     * @access private
 179     */
 180    var $_logfile = 'Net_SmartIRC.log';
 181    
 182    /**
 183     * @var integer
 184     * @access private
 185     */
 186    var $_disconnecttime = 1000;
 187    
 188    /**
 189     * @var boolean
 190     * @access private
 191     */
 192    var $_loggedin = false;
 193    
 194    /**
 195     * @var boolean
 196     * @access private
 197     */
 198    var $_benchmark = false;
 199    
 200    /**
 201     * @var integer
 202     * @access private
 203     */
 204    var $_benchmark_starttime;
 205    
 206    /**
 207     * @var integer
 208     * @access private
 209     */
 210    var $_benchmark_stoptime;
 211    
 212    /**
 213     * @var integer
 214     * @access private
 215     */
 216    var $_actionhandlerid = 0;
 217    
 218    /**
 219     * @var integer
 220     * @access private
 221     */
 222    var $_timehandlerid = 0;
 223    
 224    /**
 225     * @var array
 226     * @access private
 227     */
 228    var $_motd = array();
 229    
 230    /**
 231     * @var array
 232     * @access private
 233     */
 234    var $_channels = array();
 235    
 236    /**
 237     * @var boolean
 238     * @access private
 239     */
 240    var $_channelsyncing = false;
 241    
 242    /**
 243     * @var string
 244     * @access private
 245     */
 246    var $_ctcpversion;
 247    
 248    /**
 249     * @var mixed
 250     * @access private
 251     */
 252    var $_mintimer = false;
 253    
 254    /**
 255     * @var integer
 256     * @access private
 257     */
 258    var $_maxtimer = 300000;
 259    
 260    /**
 261     * @var integer
 262     * @access private
 263     */
 264    var $_txtimeout = 300;
 265    
 266    /**
 267     * @var integer
 268     * @access private
 269     */
 270    var $_rxtimeout = 300;
 271    
 272    /**
 273     * @var integer
 274     * @access private
 275     */
 276    var $_selecttimeout;
 277    
 278    /**
 279     * @var integer
 280     * @access private
 281     */
 282    var $_lastrx;
 283    
 284    /**
 285     * @var integer
 286     * @access private
 287     */
 288    var $_lasttx;
 289    
 290    /**
 291     * @var boolean
 292     * @access private
 293     */
 294    var $_autoreconnect = false;
 295    
 296    /**
 297     * @var boolean
 298     * @access private
 299     */
 300    var $_autoretry = false;
 301    
 302    /**
 303     * All IRC replycodes, the index is the replycode name.
 304     *
 305     * @see $SMARTIRC_replycodes
 306     * @var array
 307     * @access public
 308     */
 309    var $replycodes;
 310    
 311    /**
 312     * All numeric IRC replycodes, the index is the numeric replycode.
 313     *
 314     * @see $SMARTIRC_nreplycodes
 315     * @var array
 316     * @access public
 317     */
 318    var $nreplycodes;
 319    
 320    /**
 321     * Stores all channels in this array where we are joined, works only if channelsyncing is activated.
 322     * Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
 323     * $irc->channel['#test']->users['meebey']->nick;
 324     *
 325     * @see setChannelSyncing()
 326     * @see Net_SmartIRC_channel
 327     * @see Net_SmartIRC_channeluser
 328     * @var array
 329     * @access public
 330     */
 331    var $channel;
 332    
 333    /**
 334     * Constructor. Initiales the messagebuffer and "links" the replycodes from
 335     * global into properties. Also some PHP runtime settings are configured.
 336     *
 337     * @access public
 338     * @return void
 339     */
 340    function Net_SmartIRC_base()
 341    {
 342        // precheck
 343        $this->_checkPHPVersion();
 344        
 345        ob_implicit_flush(true);
 346        @set_time_limit(0);
 347        ignore_user_abort(true);
 348        $this->_messagebuffer[SMARTIRC_CRITICAL] = array();
 349        $this->_messagebuffer[SMARTIRC_HIGH] = array();
 350        $this->_messagebuffer[SMARTIRC_MEDIUM] = array();
 351        $this->_messagebuffer[SMARTIRC_LOW] = array();
 352        $this->replycodes = &$GLOBALS['SMARTIRC_replycodes'];
 353        $this->nreplycodes = &$GLOBALS['SMARTIRC_nreplycodes'];
 354        
 355        // hack till PHP allows (PHP5) $object->method($param)->$object
 356        $this->channel = &$this->_channels;
 357        // another hack
 358        $this->user = &$this->_users;
 359        
 360        if (isset($_SERVER['REQUEST_METHOD'])) {
 361            // the script is called from a browser, lets set default log destination
 362            // to SMARTIRC_BROWSEROUT (makes browser friendly output)
 363            $this->setLogdestination(SMARTIRC_BROWSEROUT);
 364        }
 365    }
 366    
 367    /**
 368     * Enables/disables the usage of real sockets.
 369     *
 370     * Enables/disables the usage of real sockets instead of fsocks
 371     * (works only if your PHP build has loaded the PHP socket extension)
 372     * Default: false
 373     *
 374     * @param bool $boolean
 375     * @return void
 376     * @access public
 377     */
 378    function setUseSockets($boolean)
 379    {
 380        if ($boolean === true) {
 381            if (@extension_loaded('sockets')) {
 382                $this->_usesockets = true;
 383            } else {
 384                $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket extension not loaded, trying to load it...', __FILE__, __LINE__);
 385                
 386                if (strtoupper(substr(PHP_OS, 0,3) == 'WIN')) {
 387                    $load_status = @dl('php_sockets.dll');
 388                } else {
 389                    $load_status = @dl('sockets.so');
 390                }
 391 
 392                if ($load_status) {
 393                    $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket extension succesfully loaded', __FILE__, __LINE__);
 394                    $this->_usesockets = true;
 395                } else {
 396                    $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: couldn\'t load the socket extension', __FILE__, __LINE__);
 397                    $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: your PHP build doesn\'t support real sockets, will use fsocks instead', __FILE__, __LINE__);
 398                    $this->_usesockets = false;
 399                }
 400            }
 401        } else {
 402            $this->_usesockets = false;
 403        }
 404    }
 405    
 406    /**
 407     * Sets the level of debug messages.
 408     *
 409     * Sets the debug level (bitwise), useful for testing/developing your code.
 410     * Here the list of all possible debug levels:
 411     * SMARTIRC_DEBUG_NONE
 412     * SMARTIRC_DEBUG_NOTICE
 413     * SMARTIRC_DEBUG_CONNECTION
 414     * SMARTIRC_DEBUG_SOCKET
 415     * SMARTIRC_DEBUG_IRCMESSAGES
 416     * SMARTIRC_DEBUG_MESSAGETYPES
 417     * SMARTIRC_DEBUG_ACTIONHANDLER
 418     * SMARTIRC_DEBUG_TIMEHANDLER
 419     * SMARTIRC_DEBUG_MESSAGEHANDLER
 420     * SMARTIRC_DEBUG_CHANNELSYNCING
 421     * SMARTIRC_DEBUG_MODULES
 422     * SMARTIRC_DEBUG_USERSYNCING
 423     * SMARTIRC_DEBUG_ALL
 424     *
 425     * Default: SMARTIRC_DEBUG_NOTICE
 426     *
 427     * @see DOCUMENTATION
 428     * @see SMARTIRC_DEBUG_NOTICE
 429     * @param integer $level
 430     * @return void
 431     * @access public
 432     */
 433    function setDebug($level)
 434    {
 435        $this->_debug = $level;
 436    }
 437    
 438    /**
 439     * Enables/disables the benchmark engine.
 440     * 
 441     * @param boolean $boolean
 442     * @return void
 443     * @access public
 444     */
 445    function setBenchmark($boolean)
 446    {
 447        if (is_bool($boolean)) {
 448            $this->_benchmark = $boolean;
 449        } else {
 450            $this->_benchmark = false;
 451        }
 452    }
 453    
 454    /**
 455     * Deprecated, use setChannelSyncing() instead!
 456     *
 457     * @deprecated
 458     * @param boolean $boolean
 459     * @return void
 460     * @access public
 461     */
 462    function setChannelSynching($boolean)
 463    {
 464        $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: you are using setChannelSynching() which is a deprecated method, use setChannelSyncing() instead!', __FILE__, __LINE__);
 465        $this->setChannelSyncing($boolean);
 466    }
 467    
 468    /**
 469     * Enables/disables channel syncing.
 470     *
 471     * Channel syncing means, all users on all channel we are joined are tracked in the
 472     * channel array. This makes it very handy for botcoding.
 473     * 
 474     * @param boolean $boolean
 475     * @return void
 476     * @access public
 477     */
 478    function setChannelSyncing($boolean)
 479    {
 480        if (is_bool($boolean)) {
 481            $this->_channelsyncing = $boolean;
 482        } else {
 483            $this->_channelsyncing = false;
 484        }
 485        
 486        if ($this->_channelsyncing == true) {
 487            $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: Channel syncing enabled', __FILE__, __LINE__);
 488        } else {
 489            $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: Channel syncing disabled', __FILE__, __LINE__);
 490        }
 491    }
 492    
 493    /**
 494     * Sets the CTCP version reply string.
 495     * 
 496     * @param string $versionstring
 497     * @return void
 498     * @access public
 499     */
 500    function setCtcpVersion($versionstring)
 501    {
 502        $this->_ctcpversion = $versionstring;
 503    }
 504    
 505    /**
 506     * Sets the destination of all log messages.
 507     *
 508     * Sets the destination of log messages.
 509     * $type can be:
 510     * SMARTIRC_FILE for saving the log into a file
 511     * SMARTIRC_STDOUT for echoing the log to stdout
 512     * SMARTIRC_SYSLOG for sending the log to the syslog
 513     * Default: SMARTIRC_STDOUT
 514     *
 515     * @see SMARTIRC_STDOUT
 516     * @param integer $type must be on of the constants
 517     * @return void
 518     * @access public
 519     */
 520    function setLogdestination($type)
 521    {
 522        switch ($type) {
 523            case (SMARTIRC_FILE ||
 524                  SMARTIRC_STDOUT ||
 525                  SMARTIRC_SYSLOG ||
 526                  SMARTIRC_BROWSEROUT ||
 527                  SMARTIRC_NONE):
 528                $this->_logdestination = $type;
 529            break;
 530            default:
 531                $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: unknown logdestination type ('.$type.'), will use STDOUT instead', __FILE__, __LINE__);
 532                $this->_logdestination = SMARTIRC_STDOUT;
 533        }
 534    }
 535    
 536    /**
 537     * Sets the file for the log if the destination is set to file.
 538     *
 539     * Sets the logfile, if {@link setLogdestination logdestination} is set to SMARTIRC_FILE.
 540     * This should be only used with full path!
 541     *
 542     * @param string $file 
 543     * @return void
 544     * @access public
 545     */
 546    function setLogfile($file)
 547    {
 548        $this->_logfile = $file;
 549    }
 550    
 551    /**
 552     * Sets the delaytime before closing the socket when disconnect.
 553     *
 554     * @param integer $milliseconds
 555     * @return void
 556     * @access public
 557     */
 558    function setDisconnecttime($milliseconds)
 559    {
 560        if (is_integer($milliseconds) && $milliseconds >= 100) {
 561            $this->_disconnecttime = $milliseconds;
 562        } else {
 563            $this->_disconnecttime = 100;
 564        }
 565    }
 566    
 567    /**
 568     * Sets the delay for receiving data from the IRC server.
 569     *
 570     * Sets the delaytime between messages that are received, this reduces your CPU load.
 571     * Don't set this too low (min 100ms).
 572     * Default: 100
 573     *
 574     * @param integer $milliseconds
 575     * @return void
 576     * @access public
 577     */
 578    function setReceivedelay($milliseconds)
 579    {
 580        if (is_integer($milliseconds) && $milliseconds >= 100) {
 581            $this->_receivedelay = $milliseconds;
 582        } else {
 583            $this->_receivedelay = 100;
 584        }
 585    }
 586    
 587    /**
 588     * Sets the delay for sending data to the IRC server.
 589     *
 590     * Sets the delaytime between messages that are sent, because IRC servers doesn't like floods.
 591     * This will avoid sending your messages too fast to the IRC server.
 592     * Default: 250
 593     *
 594     * @param integer $milliseconds
 595     * @return void
 596     * @access public
 597     */
 598    function setSenddelay($milliseconds)
 599    {
 600        if (is_integer($milliseconds)) {
 601            $this->_senddelay = $milliseconds;
 602        } else {
 603            $this->_senddelay = 250;
 604        }
 605    }
 606    
 607    /**
 608     * Enables/disables autoreconnecting.
 609     * 
 610     * @param boolean $boolean
 611     * @return void
 612     * @access public
 613     */
 614    function setAutoReconnect($boolean)
 615    {
 616        if (is_bool($boolean)) {
 617            $this->_autoreconnect = $boolean;
 618        } else {
 619            $this->_autoreconnect = false;
 620        }
 621    }
 622    
 623    /**
 624     * Enables/disables autoretry for connecting to a server.
 625     * 
 626     * @param boolean $boolean
 627     * @return void
 628     * @access public
 629     */
 630    function setAutoRetry($boolean)
 631    {
 632        if (is_bool($boolean)) {
 633            $this->_autoretry = $boolean;
 634        } else {
 635            $this->_autoretry = false;
 636        }
 637    }
 638    
 639    /**
 640     * Sets the receive timeout.
 641     *
 642     * If the timeout occurs, the connection will be reinitialized
 643     * Default: 300 seconds
 644     *
 645     * @param integer $seconds
 646     * @return void
 647     * @access public
 648     */
 649    function setReceiveTimeout($seconds)
 650    {
 651        if (is_integer($seconds)) {
 652            $this->_rxtimeout = $seconds;
 653        } else {
 654            $this->_rxtimeout = 300;
 655        }
 656    }
 657    
 658    /**
 659     * Sets the transmit timeout.
 660     *
 661     * If the timeout occurs, the connection will be reinitialized
 662     * Default: 300 seconds
 663     *
 664     * @param integer $seconds
 665     * @return void
 666     * @access public
 667     */
 668    function setTransmitTimeout($seconds)
 669    {
 670        if (is_integer($seconds)) {
 671            $this->_txtimeout = $seconds;
 672        } else {
 673            $this->_txtimeout = 300;
 674        }
 675    }
 676    
 677    /**
 678     * Starts the benchmark (sets the counters).
 679     *
 680     * @return void
 681     * @access public
 682     */
 683    function startBenchmark()
 684    {
 685        $this->_benchmark_starttime = $this->_microint();
 686        $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark started', __FILE__, __LINE__);
 687    }
 688    
 689    /**
 690     * Stops the benchmark and displays the result.
 691     *
 692     * @return void
 693     * @access public
 694     */
 695    function stopBenchmark()
 696    {
 697        $this->_benchmark_stoptime = $this->_microint();
 698        $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark stopped', __FILE__, __LINE__);
 699        
 700        if ($this->_benchmark) {
 701            $this->showBenchmark();
 702        }
 703    }
 704    
 705    /**
 706     * Shows the benchmark result.
 707     *
 708     * @return void
 709     * @access public
 710     */
 711    function showBenchmark()
 712    {
 713        $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark time: '.((float)$this->_benchmark_stoptime-(float)$this->_benchmark_starttime), __FILE__, __LINE__);
 714    }
 715    
 716    /**
 717     * Adds an entry to the log.
 718     *
 719     * Adds an entry to the log with Linux style log format.
 720     * Possible $level constants (can also be combined with "|"s)
 721     * SMARTIRC_DEBUG_NONE
 722     * SMARTIRC_DEBUG_NOTICE
 723     * SMARTIRC_DEBUG_CONNECTION
 724     * SMARTIRC_DEBUG_SOCKET
 725     * SMARTIRC_DEBUG_IRCMESSAGES
 726     * SMARTIRC_DEBUG_MESSAGETYPES
 727     * SMARTIRC_DEBUG_ACTIONHANDLER
 728     * SMARTIRC_DEBUG_TIMEHANDLER
 729     * SMARTIRC_DEBUG_MESSAGEHANDLER
 730     * SMARTIRC_DEBUG_CHANNELSYNCING
 731     * SMARTIRC_DEBUG_MODULES
 732     * SMARTIRC_DEBUG_USERSYNCING
 733     * SMARTIRC_DEBUG_ALL
 734     *
 735     * @see SMARTIRC_DEBUG_NOTICE
 736     * @param integer $level bit constants (SMARTIRC_DEBUG_*)
 737     * @param string $entry the new log entry
 738     * @return void
 739     * @access public
 740     */
 741    function log($level, $entry, $file = null, $line = null)
 742    {
 743        // prechecks
 744        if (!(is_integer($level)) ||
 745            !($level & SMARTIRC_DEBUG_ALL)) {
 746            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: invalid log level passed to log() ('.$level.')', __FILE__, __LINE__);
 747            return;
 748        }
 749        
 750        if (!($level & $this->_debug) ||
 751             ($this->_logdestination == SMARTIRC_NONE)) {
 752            return;
 753        }
 754        
 755        if (substr($entry, -1) != "\n") {
 756            $entry .= "\n";
 757        }
 758        
 759        if ($file !== null &&
 760            $line !== null) {
 761            $file = basename($file);
 762            $entry = $file.'('.$line.') '.$entry;
 763        } else {
 764            $entry = 'unknown(0) '.$entry;
 765        }
 766        
 767        $formatedentry = date('M d H:i:s ').$entry;
 768        switch ($this->_logdestination) {
 769            case SMARTIRC_STDOUT:
 770                echo $formatedentry;
 771                flush();
 772            break;
 773            case SMARTIRC_BROWSEROUT:
 774                echo '<pre>'.htmlentities($formatedentry).'</pre>';
 775            break;
 776            case SMARTIRC_FILE:
 777                if (!is_resource($this->_logfilefp)) {
 778                    if ($this->_logfilefp === null) {
 779                        // we reconncted and don't want to destroy the old log entries
 780                        $this->_logfilefp = @fopen($this->_logfile,'a');
 781                    } else {
 782                        $this->_logfilefp = @fopen($this->_logfile,'w');
 783                    }
 784                }
 785                @fwrite($this->_logfilefp, $formatedentry);
 786                fflush($this->_logfilefp);
 787            break;
 788            case SMARTIRC_SYSLOG:
 789                define_syslog_variables();
 790                if (!is_int($this->_logfilefp)) {
 791                    $this->_logfilefp = openlog('Net_SmartIRC', LOG_NDELAY, LOG_DAEMON);
 792                }
 793                syslog(LOG_INFO, $entry);
 794            break;
 795        }
 796    }
 797    
 798    /**
 799     * Returns the full motd.
 800     *
 801     * @return array
 802     * @access public
 803     */
 804    function getMotd()
 805    {
 806        return $this->_motd;
 807    }
 808    
 809    /**
 810     * Returns the usermode.
 811     *
 812     * @return string
 813     * @access public
 814     */
 815    function getUsermode()
 816    {
 817        return $this->_usermode;
 818    }
 819    
 820    /**
 821     * Creates the sockets and connects to the IRC server on the given port.
 822     *
 823     * @param string $address 
 824     * @param integer $port
 825     * @return void
 826     * @access public
 827     */
 828    function connect($address, $port)
 829    {
 830        $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connecting', __FILE__, __LINE__);
 831        $this->_address = $address;
 832        $this->_port = $port;
 833        
 834        if ($this->_usesockets == true) {
 835            $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: using real sockets', __FILE__, __LINE__);
 836            $this->_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
 837            $result = @socket_connect($this->_socket, $this->_address, $this->_port);
 838        } else {
 839            $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: using fsockets', __FILE__, __LINE__);
 840            $result = @fsockopen($this->_address, $this->_port, $errno, $errstr);
 841        }
 842        
 843        if ($result === false) {
 844            if ($this->_usesockets == true) {
 845                $error = socket_strerror(socket_last_error($this->_socket));
 846            } else {
 847                $error = $errstr.' ('.$errno.')';
 848            }
 849            
 850            $error_msg = 'couldn\'t connect to "'.$address.'" reason: "'.$error.'"';
 851            $this->log(SMARTIRC_DEBUG_NOTICE, 'DEBUG_NOTICE: '.$error_msg, __FILE__, __LINE__);
 852            // TODO! muss return wert sein
 853            $this->throwError($error_msg);
 854            
 855            // doesn't work somehow.... I only want to retry 4 times! no endless loop (causes segfault)
 856            static $tries = 0;
 857            if ($this->_autoretry == true && $tries < 5) {
 858                $this->reconnect();
 859                $tries++;
 860            } else {
 861                die();
 862            }
 863        } else {
 864            $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connected', __FILE__, __LINE__);
 865            
 866            if ($this->_usesockets != true) {
 867                $this->_socket = $result;
 868                $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: activating nonblocking fsocket mode', __FILE__, __LINE__);
 869                socket_set_blocking($this->_socket, false);
 870            }
 871        }
 872        
 873        $this->_lastrx = time();
 874        $this->_lasttx = $this->_lastrx;
 875        $this->_updatestate();
 876        
 877        if ($result !== false) {
 878            return true;
 879        } else {
 880            return false;
 881        }
 882    }
 883    
 884    /**
 885     * Disconnects from the IRC server nicely with a QUIT or just destroys the socket.
 886     *
 887     * Disconnects from the IRC server in the given quickness mode.
 888     * $quickdisconnect:
 889     * true, just close the socket
 890     * false, send QUIT and wait {@link $_disconnectime $_disconnectime} before closing the socket
 891     *
 892     * @param boolean $quickdisconnect default: false
 893     * @return boolean
 894     * @access public
 895     */
 896    function disconnect($quickdisconnect = false)
 897    {
 898        if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
 899            if ($quickdisconnect == false) {
 900                $this->_send('QUIT', SMARTIRC_CRITICAL);
 901                usleep($this->_disconnecttime*1000);
 902            }
 903            
 904            if ($this->_usesockets == true) {
 905                @socket_shutdown($this->_socket);
 906                @socket_close($this->_socket);
 907            } else {
 908                fclose($this->_socket);
 909            }
 910            
 911            $this->_updatestate();
 912            $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: disconnected', __FILE__, __LINE__);
 913        } else {
 914            return false;
 915        }
 916        
 917        if ($this->_channelsyncing == true) {
 918            // let's clean our channel array
 919            $this->_channels = array();
 920            $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: cleaned channel array', __FILE__, __LINE__);
 921        }
 922        
 923        if ($this->_logdestination == SMARTIRC_FILE) {
 924            fclose($this->_logfilefp);
 925            $this->_logfilefp = null;
 926        } else if ($this->_logdestination == SMARTIRC_SYSLOG) {
 927            closelog();
 928        }
 929        
 930        return true;
 931    }
 932    
 933    /**
 934     * Reconnects to the IRC server with the same login info,
 935     * it also rejoins the channels
 936     *
 937     * @return void
 938     * @access public
 939     */
 940    function reconnect()
 941    {
 942        $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: reconnecting...', __FILE__, __LINE__);
 943        
 944        // remember in which channels we are joined
 945        $channels = array();
 946        foreach ($this->_channels as $value) {
 947            if (empty($value->key)) {
 948                $channels[] = array('name' => $value->name);
 949            } else {
 950                $channels[] = array('name' => $value->name, 'key' => $value->key);
 951            }
 952        }
 953        
 954        $this->disconnect(true);
 955        $this->connect($this->_address, $this->_port);
 956        $this->login($this->_nick, $this->_realname, $this->_usermode, $this->_username, $this->_password);
 957        
 958        // rejoin the channels
 959        foreach ($channels as $value) {
 960            if (isset($value['key'])) {
 961                $this->join($value['name'], $value['key']);
 962            } else {
 963                $this->join($value['name']);
 964            }
 965        }
 966    }
 967    
 968    /**
 969     * login and register nickname on the IRC network
 970     *
 971     * Registers the nickname and user information on the IRC network.
 972     *
 973     * @param string $nick
 974     * @param string $realname
 975     * @param integer $usermode
 976     * @param string $username
 977     * @param string $password
 978     * @return void
 979     * @access public
 980     */
 981    function login($nick, $realname, $usermode = 0, $username = null, $password = null)
 982    {
 983        $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: logging in', __FILE__, __LINE__);
 984        
 985        $this->_nick = str_replace(' ', '', $nick);
 986        $this->_realname = $realname;
 987        
 988        if ($username !== null) {
 989            $this->_username = str_replace(' ', '', $username);
 990        } else {
 991            $this->_username = str_replace(' ', '', exec('whoami'));
 992        }
 993        
 994        if ($password !== null) {
 995            $this->_password = $password;
 996            $this->_send('PASS '.$this->_password, SMARTIRC_CRITICAL);
 997        }
 998        
 999        if (!is_numeric($usermode)) {
1000            $this->log(SMARTIRC_DEBUG_NOTICE, 'DEBUG_NOTICE: login() usermode ('.$usermode.') is not valid, will use 0 instead', __FILE__, __LINE__);
1001            $usermode = 0;
1002        }
1003        
1004        $this->_send('NICK '.$this->_nick, SMARTIRC_CRITICAL);
1005        $this->_send('USER '.$this->_username.' '.$usermode.' '.SMARTIRC_UNUSED.' :'.$this->_realname, SMARTIRC_CRITICAL);
1006    }
1007    
1008    // </IRC methods>
1009    
1010    /**
1011     * checks if we or the given user is joined to the specified channel and returns the result
1012     * ChannelSyncing is required for this.
1013     *
1014     * @see setChannelSyncing
1015     * @param string $channel
1016     * @param string $nickname
1017     * @return boolean
1018     * @access public
1019     */
1020    function isJoined($channel, $nickname = null)
1021    {
1022        if ($this->_channelsyncing != true) {
1023            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isJoined() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
1024            return false;
1025        }
1026        
1027        if ($nickname === null) {
1028            $nickname = $this->_nick;
1029        }
1030        
1031        if (isset($this->_channels[strtolower($channel)]->users[strtolower($nickname)])) {
1032            return true;
1033        }
1034        
1035        return false;
1036    }
1037    
1038    /**
1039     * Checks if we or the given user is opped on the specified channel and returns the result.
1040     * ChannelSyncing is required for this.
1041     *
1042     * @see setChannelSyncing
1043     * @param string $channel
1044     * @param string $nickname
1045     * @return boolean
1046     * @access public
1047     */
1048    function isOpped($channel, $nickname = null)
1049    {
1050        if ($this->_channelsyncing != true) {
1051            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isOpped() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
1052            return false;
1053        }
1054        
1055        if ($nickname === null) {
1056            $nickname = $this->_nick;
1057        }
1058        
1059        if ($this->isJoined($channel, $nickname)) {
1060            if ($this->_channels[strtolower($channel)]->users[strtolower($nickname)]->op) {
1061                return true;
1062            }
1063        }
1064        
1065        return false;
1066    }
1067    
1068    /**
1069     * Checks if we or the given user is voiced on the specified channel and returns the result.
1070     * ChannelSyncing is required for this.
1071     *
1072     * @see setChannelSyncing
1073     * @param string $channel
1074     * @param string $nickname
1075     * @return boolean
1076     * @access public
1077     */
1078    function isVoiced($channel, $nickname = null)
1079    {
1080        if ($this->_channelsyncing != true) {
1081            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isVoiced() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
1082            return false;
1083        }
1084        
1085        if ($nickname === null) {
1086            $nickname = $this->_nick;
1087        }
1088        
1089        if ($this->isJoined($channel, $nickname)) {
1090            if ($this->_channels[strtolower($channel)]->users[strtolower($nickname)]->voice) {
1091                return true;
1092            }
1093        }
1094        
1095        return false;
1096    }
1097    
1098    /**
1099     * Checks if the hostmask is on the specified channel banned and returns the result.
1100     * ChannelSyncing is required for this.
1101     *
1102     * @see setChannelSyncing
1103     * @param string $channel
1104     * @param string $hostmask
1105     * @return boolean
1106     * @access public
1107     */
1108    function isBanned($channel, $hostmask)
1109    {
1110        if ($this->_channelsyncing != true) {
1111            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isBanned() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
1112            return false;
1113        }
1114        
1115        if ($this->isJoined($channel)) {
1116            $result = array_search($hostmask, $this->_channels[strtolower($channel)]->bans);
1117            
1118            if ($result !== false) {
1119                return true;
1120            }
1121        }
1122        
1123        return false;
1124    }
1125
1126    /**
1127     * goes into receive mode
1128     *
1129     * Goes into receive and idle mode. Only call this if you want to "spawn" the bot.
1130     * No further lines of PHP code will be processed after this call, only the bot methods!
1131     *
1132     * @return boolean
1133     * @access public
1134     */
1135    function listen()
1136    {
1137        if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
1138            $this->_rawreceive();
1139            return true;
1140        } else {
1141            return false;
1142        }
1143    }
1144    
1145    /**
1146     * waits for a special message type and puts the answer in $result
1147     *
1148     * Creates a special actionhandler for that given TYPE and returns the answer.
1149     * This will only receive the requested type, immediately quit and disconnect from the IRC server.
1150     * Made for showing IRC statistics on your homepage, or other IRC related information.
1151     *
1152     * @param integer $messagetype see in the documentation 'Message Types'
1153     * @return array answer from the IRC server for this $messagetype
1154     * @access public
1155     */
1156    function listenFor($messagetype)
1157    {
1158        $listenfor = &new Net_SmartIRC_listenfor();
1159        $this->registerActionhandler($messagetype, '.*', $listenfor, 'handler');
1160        $this->listen();
1161        $result = $listenfor->result;
1162        
1163        if (isset($listenfor)) {
1164            unset($listenfor);
1165        }
1166        
1167        return $result;
1168    }
1169    
1170    /**
1171     * waits for a special message type and puts the answer in $result
1172     *
1173     * Creates a special actionhandler for that given TYPE and returns the answer.
1174     * This will only receive the requested type, immediately quit and disconnect from the IRC server.
1175     * Made for showing IRC statistics on your homepage, or other IRC related information.
1176     * This special version of listenFor() stores the whole ircdata object, not just the message!
1177     *
1178     * @param integer $messagetype see in the documentation 'Message Types'
1179     * @return array answer from the IRC server for this $messagetype
1180     * @access public
1181     */
1182    function objListenFor($messagetype)
1183    {
1184        $objlistenfor = &new Net_SmartIRC_objListenFor();
1185        $this->registerActionhandler($messagetype, '.*', $objlistenfor, 'handler');
1186        $this->listen();
1187        $result = $objlistenfor->result;
1188        
1189        if (isset($objlistenfor)) {
1190            unset($objlistenfor);
1191        }
1192        
1193        return $result;
1194    }    
1195    
1196    /**
1197     * registers a new actionhandler and returns the assigned id
1198     *
1199     * Registers an actionhandler in Net_SmartIRC for calling it later.
1200     * The actionhandler id is needed for unregistering the actionhandler.
1201     *
1202     * @see example.php
1203     * @param integer $handlertype bits constants, see in this documentation Message Types
1204     * @param string $regexhandler the message that has to be in the IRC message in regex syntax
1205     * @param object $object a reference to the objects of the method
1206     * @param string $methodname the methodname that will be called when the handler happens
1207     * @return integer assigned actionhandler id
1208     * @access public
1209     */
1210    function registerActionhandler($handlertype, $regexhandler, &$object, $methodname)
1211    {
1212        // precheck
1213        if (!$this->_isValidType($handlertype)) {
1214            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: passed invalid handlertype to registerActionhandler()', __FILE__, __LINE__);
1215            return false;
1216        }
1217        
1218        $id = $this->_actionhandlerid++;
1219        $newactionhandler = &new Net_SmartIRC_actionhandler();
1220        
1221        $newactionhandler->id = $id;
1222        $newactionhandler->type = $handlertype;
1223        $newactionhandler->message = $regexhandler;
1224        $newactionhandler->object = &$object;
1225        $newactionhandler->method = $methodname;
1226        
1227        $this->_actionhandler[] = &$newactionhandler;
1228        $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') registered', __FILE__, __LINE__);
1229        return $id;
1230    }
1231    
1232    /**
1233     * unregisters an existing actionhandler
1234     *
1235     * @param integer $handlertype
1236     * @param string $regexhandler
1237     * @param object $object
1238     * @param string $methodname
1239     * @return boolean
1240     * @access public
1241     */
1242    function unregisterActionhandler($handlertype, $regexhandler, &$object, $methodname)
1243    {
1244        // precheck
1245        if (!$this->_isValidType($handlertype)) {
1246            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: passed invalid handlertype to unregisterActionhandler()', __FILE__, __LINE__);
1247            return false;
1248        }
1249        
1250        $handler = &$this->_actionhandler;
1251        $handlercount = count($handler);
1252        
1253        for ($i = 0; $i < $handlercount; $i++) {
1254            $handlerobject = &$handler[$i];
1255                        
1256            if ($handlerobject->type == $handlertype &&
1257                $handlerobject->message == $regexhandler &&
1258                $handlerobject->method == $methodname) {
1259                
1260                $id = $handlerobject->id;
1261                
1262                if (isset($this->_actionhandler[$i])) {
1263                    unset($this->_actionhandler[$i]);
1264                }
1265                
1266                $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') unregistered', __FILE__, __LINE__);
1267                $this->_reorderactionhandler();
1268                return true;
1269            }
1270        }
1271        
1272        $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: could not find actionhandler type: "'.$handlertype.'" message: "'.$regexhandler.'" method: "'.$methodname.'" from object "'.get_class($object).'" _not_ unregistered', __FILE__, __LINE__);
1273        return false;
1274    }
1275    
1276    /**
1277     * unregisters an existing actionhandler via the id
1278     *
1279     * @param integer $id
1280     * @return boolean
1281     * @access public
1282     */
1283    function unregisterActionid($id)
1284    {
1285        $handler = &$this->_actionhandler;
1286        $handlercount = count($handler);
1287        for ($i = 0; $i < $handlercount; $i++) {
1288            $handlerobject = &$handler[$i];
1289                        
1290            if ($handlerobject->id == $id) {
1291                if (isset($this->_actionhandler[$i])) {
1292                    unset($this->_actionhandler[$i]);
1293                }
1294                
1295                $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') unregistered', __FILE__, __LINE__);
1296                $this->_reorderactionhandler();
1297                return true;
1298            }
1299        }
1300        
1301        $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: could not find actionhandler id: '.$id.' _not_ unregistered', __FILE__, __LINE__);
1302        return false;
1303    }
1304    
1305    /**
1306     * registers a timehandler and returns the assigned id
1307     *
1308     * Registers a timehandler in Net_SmartIRC, which will be called in the specified interval.
1309     * The timehandler id is needed for unregistering the timehandler.
1310     *
1311     * @see example7.php
1312     * @param integer $interval interval time in milliseconds
1313     * @param object $object a reference to the objects of the method
1314     * @param string $methodname the methodname that will be called when the handler happens
1315     * @return integer assigned timehandler id
1316     * @access public
1317     */
1318    function registerTimehandler($interval, &$object, $methodname)
1319    {
1320        $id = $this->_timehandlerid++;
1321        $newtimehandler = &new Net_SmartIRC_timehandler();
1322        
1323        $newtimehandler->id = $id;
1324        $newtimehandler->interval = $interval;
1325        $newtimehandler->object = &$object;
1326        $newtimehandler->method = $methodname;
1327        $newtimehandler->lastmicrotimestamp = $this->_microint();
1328        
1329        $this->_timehandler[] = &$newtimehandler;
1330        $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: timehandler('.$id.') registered', __FILE__, __LINE__);
1331        
1332        if (($interval < $this->_mintimer) || ($this->_mintimer == false)) {
1333            $this->_mintimer = $interval;
1334        }
1335            
1336        return $id;
1337    }
1338    
1339    /**
1340     * unregisters an existing timehandler via the id
1341     *
1342     * @see example7.php
1343     * @param integer $id
1344     * @return boolean
1345     * @access public
1346     */
1347    function unregisterTimeid($id)
1348    {
1349        $handler = &$this->_timehandler;
1350        $handlercount = count($handler);
1351        for ($i = 0; $i < $handlercount; $i++) {
1352            $handlerobject = &$handler[$i];
1353            
1354            if ($handlerobject->id == $id) {
1355                if (isset($this->_timehandler[$i])) {
1356                    unset($this->_timehandler[$i]);
1357                }
1358                
1359                $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: timehandler('.$id.') unregistered', __FILE__, __LINE__);
1360                $this->_reordertimehandler();
1361                $this->_updatemintimer();
1362                return true;
1363            }
1364        }
1365        
1366        $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: could not find timehandler id: '.$id.' _not_ unregistered', __FILE__, __LINE__);
1367        return false;
1368    }
1369    
1370    // <private methods>
1371    /**
1372     * changes a already used nickname to a new nickname plus 3 random digits
1373     *
1374     * @return void
1375     * @access private
1376     */
1377    function _nicknameinuse()
1378    {
1379        $newnickname = substr($this->_nick, 0, 5).rand(0, 999);
1380        $this->changeNick($newnickname, SMARTIRC_CRITICAL);
1381    }
1382    
1383    /**
1384     * sends an IRC message
1385     *
1386     * Adds a message to the messagequeue, with the optional priority.
1387     * $priority:
1388     * SMARTIRC_CRITICAL
1389     * SMARTIRC_HIGH
1390     * SMARTIRC_MEDIUM
1391     * SMARTIRC_LOW
1392     *
1393     * @param string $data
1394     * @param integer $priority must be one of the priority constants
1395     * @return boolean
1396     * @access private
1397     */
1398    function _send($data, $priority = SMARTIRC_MEDIUM)
1399    {
1400        switch ($priority) {
1401            case SMARTIRC_CRITICAL:
1402                $this->_rawsend($data);
1403                return true;
1404            break;
1405            case (SMARTIRC_HIGH||
1406                  SMARTIRC_MEDIUM||
1407                  SMARTIRC_LOW):
1408                $this->_messagebuffer[$priority][] = $data;
1409                return true;
1410            break;
1411            default:
1412                $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: message ('.$data.') with an invalid priority passed ('.$priority.'), message is ignored!', __FILE__, __LINE__);
1413                return false;
1414        }
1415    }
1416    
1417    /**
1418     * checks the buffer if there are messages to send
1419     *
1420     * @return void
1421     * @access private
1422     */
1423    function _checkbuffer()
1424    {
1425        if (!$this->_loggedin) {
1426            return;
1427        }
1428        
1429        static $highsent = 0;
1430        static $lastmicrotimestamp = 0;
1431        
1432        if ($lastmicrotimestamp == 0) {
1433            $lastmicrotimestamp = $this->_microint();
1434        }
1435        
1436        $highcount = count($this->_messagebuffer[SMARTIRC_HIGH]);
1437        $mediumcount = count($this->_messagebuffer[SMARTIRC_MEDIUM]);
1438        $lowcount = count($this->_messagebuffer[SMARTIRC_LOW]);
1439        $this->_messagebuffersize = $highcount+$mediumcount+$lowcount;
1440        
1441        // don't send them too fast
1442        if ($this->_microint() >= ($lastmicrotimestamp+($this->_senddelay/1000))) {
1443            if ($highcount > 0 && $highsent <= 2) {
1444                $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_HIGH]));
1445                $lastmicrotimestamp = $this->_microint();
1446                $highsent++;
1447            } else if ($mediumcount > 0) {
1448                $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_MEDIUM]));
1449                $lastmicrotimestamp = $this->_microint();
1450                $highsent = 0;
1451            } else if ($lowcount > 0) {
1452                $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_LOW]));
1453                $lastmicrotimestamp = $this->_microint();
1454            }
1455        }
1456    }
1457    
1458    /**
1459     * Checks the running timers and calls the registered timehandler,
1460     * when the interval is reached.
1461     *
1462     * @return void
1463     * @access private
1464     */
1465    function _checktimer()
1466    {
1467        if (!$this->_loggedin) {
1468            return;
1469        }
1470        
1471        // has to be count() because the array may change during the loop!
1472        for ($i = 0; $i < count($this->_timehandler); $i++) {
1473            $handlerobject = &$this->_timehandler[$i];
1474            $microtimestamp = $this->_microint();
1475            if ($microtimestamp >= ($handlerobject->lastmicrotimestamp+($handlerobject->interval/1000))) {
1476                $methodobject = &$handlerobject->object;
1477                $method = $handlerobject->method;
1478                $handlerobject->lastmicrotimestamp = $microtimestamp;
1479                
1480                if (@method_exists($methodobject, $method)) {
1481                    $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: calling method "'.get_class($methodobject).'->'.$method.'"', __FILE__, __LINE__);
1482                    $methodobject->$method($this);
1483                }
1484            }
1485        }
1486    }
1487    
1488    /**
1489     * Checks if a receive or transmit timeout occured and reconnects if configured
1490     *
1491     * @return void
1492     * @access private
1493     */
1494    function _checktimeout()
1495    {
1496        if ($this->_autoreconnect == true) {
1497            $timestamp = time();
1498            if ($this->_lastrx < ($timestamp - $this->_rxtimeout)) {
1499                $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: receive timeout detected, doing reconnect...', __FILE__, __LINE__);
1500                $this->reconnect();
1501            } else if ($this->_lasttx < ($timestamp - $this->_txtimeout)) {
1502                $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: transmit timeout detected, doing reconnect...', __FILE__, __LINE__);
1503                $this->reconnect();
1504            }
1505        }
1506    }
1507    
1508    /**
1509     * sends a raw message to the IRC server (don't use this!!)
1510     *
1511     * Use message() or _send() instead.
1512     *
1513     * @param string $data
1514     * @return boolean
1515     * @access private
1516     */
1517    function _rawsend($data)
1518    {
1519        if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
1520            $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: sent: "'.$data.'"', __FILE__, __LINE__);
1521            
1522            if ($this->_usesockets == true) {
1523                $result = @socket_write($this->_socket, $data.SMARTIRC_CRLF);
1524            } else {
1525                $result = @fwrite($this->_socket, $data.SMARTIRC_CRLF);
1526            }
1527            
1528            
1529            if ($result === false) {
1530                return false;
1531            } else {
1532                $this->_lasttx = time();
1533                return true;
1534            }
1535        } else {
1536            return false;
1537        }
1538    }
1539    
1540    /**
1541     * goes into main idle loop for waiting messages from the IRC server
1542     *
1543     * @return void
1544     * @access private
1545     */
1546    function _rawreceive()
1547    {
1548        $lastpart = '';
1549        $rawdataar = array();
1550        
1551        while ($this->_state() == SMARTIRC_STATE_CONNECTED) {
1552            $this->_checkbuffer();
1553            
1554            $timeout = $this->_selecttimeout();
1555            if ($this->_usesockets == true) {
1556                $sread = array($this->_socket);
1557                $result = @socket_select($sread, $w = null, $e = null, 0, $timeout*1000);
1558                
1559                if ($result == 1) {
1560                    // the socket got data to read
1561                    $rawdata = @socket_read($this->_socket, 10240);
1562                } else if ($result === false) {
1563                    // panic! panic! something went wrong!
1564                    $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket_select() returned false, something went wrong! Reason: '.socket_strerror(socket_last_error()), __FILE__, __LINE__);
1565                    exit;
1566                } else {
1567                    // no data
1568                    $rawdata = null;
1569                }
1570            } else {
1571                usleep($this->_receivedelay*1000);
1572                $rawdata = @fread($this->_socket, 10240);
1573            }
1574            
1575            $this->_checktimer();
1576            $this->_checktimeout();
1577            
1578            if ($rawdata !== null && !empty($rawdata)) {
1579                $this->_lastrx = time();
1580                $rawdata = str_replace("\r", '', $rawdata);
1581                $rawdata = $lastpart.$rawdata;
1582                
1583                $lastpart = substr($rawdata, strrpos($rawdata ,"\n")+1);
1584                $rawdata = substr($rawdata, 0, strrpos($rawdata ,"\n"));
1585                $rawdataar = explode("\n", $rawdata);
1586            }
1587            
1588            // loop through our received messages
1589            while (count($rawdataar) > 0) {
1590                $rawline = array_shift($rawdataar);
1591                $validmessage = false;
1592                
1593                $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: received: "'.$rawline.'"', __FILE__, __LINE__);
1594                
1595                // building our data packet
1596                $ircdata = &new Net_SmartIRC_data();
1597                $ircdata->rawmessage = $rawline;
1598                $lineex = explode(' ', $rawline);
1599                $ircdata->rawmessageex = $lineex;
1600                $messagecode = $lineex[0];
1601                
1602                if (substr($rawline, 0, 1) == ':') {
1603                    $validmessage = true;
1604                    $line = substr($rawline, 1);
1605                    $lineex = explode(' ', $line);
1606                    
1607                    // conform to RFC 2812
1608                    $from = $lineex[0];
1609                    $messagecode = $lineex[1];
1610                    $exclamationpos = strpos($from, '!');
1611                    $atpos = strpos($from, '@');
1612                    $colonpos = strpos($line, ' :');
1613                    if ($colonpos !== false) {
1614                        // we want the exact position of ":" not beginning from the space
1615                        $colonpos += 1;
1616                    }
1617                    $ircdata->nick = substr($from, 0, $exclamationpos);
1618                    $ircdata->ident = substr($from, $exclamationpos+1, ($atpos-$exclamationpos)-1);
1619                    $ircdata->host = substr($from, $atpos+1);
1620                    $ircdata->type = $this->_gettype($rawline);
1621                    $ircdata->from = $from;
1622                    if ($colonpos !== false) {
1623                        $ircdata->message = substr($line, $…

Large files files are truncated, but you can click here to view the full file