/lib/php/Net/SmartIRC.php
PHP | 2553 lines | 1236 code | 280 blank | 1037 comment | 297 complexity | 515caf13f9bffc1ea2efc42a31d06753 MD5 | raw file
Possible License(s): Apache-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-2-Clause, GPL-2.0, LGPL-3.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * $Id: SmartIRC.php,v 1.54.2.14 2005/05/27 23:40:09 meebey Exp $
- * $Revision: 1.54.2.14 $
- * $Author: meebey $
- * $Date: 2005/05/27 23:40:09 $
- *
- * Net_SmartIRC
- * This is a PHP class for communication with IRC networks,
- * which conforms to the RFC 2812 (IRC protocol).
- * It's an API that handles all IRC protocol messages.
- * This class is designed for creating IRC bots, chats and show irc related info on webpages.
- *
- * Documenation, a HOWTO and examples are in SmartIRC included.
- *
- * Here you will find a service bot which I am also developing
- * <http://cvs.meebey.net/atbs> and <http://cvs.meebey.net/phpbitch>
- * Latest versions of Net_SmartIRC you will find on the project homepage
- * or get it through PEAR since SmartIRC is an official PEAR package.
- * See <http://pear.php.net/Net_SmartIRC>.
- *
- * Official Projet Homepage: <http://sf.net/projects/phpsmartirc>
- *
- * Net_SmartIRC conforms to RFC 2812 (Internet Relay Chat: Client Protocol)
- *
- * Copyright (c) 2002-2003 Mirco 'meebey' Bauer <meebey@meebey.net> <http://www.meebey.net>
- *
- * Full LGPL License: <http://www.gnu.org/licenses/lgpl.txt>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- // ------- PHP code ----------
- include_once('SmartIRC/defines.php');
- include_once('SmartIRC/irccommands.php');
- include_once('SmartIRC/messagehandler.php');
- define('SMARTIRC_VERSION', '1.0.0 ($Revision: 1.54.2.14 $)');
- define('SMARTIRC_VERSIONSTRING', 'Net_SmartIRC '.SMARTIRC_VERSION);
- /**
- * main SmartIRC class
- *
- * @package Net_SmartIRC
- * @version 0.5.5
- * @author Mirco 'meebey' Bauer <mail@meebey.net>
- * @access public
- */
- class Net_SmartIRC_base
- {
- /**
- * @var resource
- * @access private
- */
- var $_socket;
-
- /**
- * @var string
- * @access private
- */
- var $_address;
-
- /**
- * @var integer
- * @access private
- */
- var $_port;
-
- /**
- * @var string
- * @access private
- */
- var $_nick;
-
- /**
- * @var string
- * @access private
- */
- var $_username;
-
- /**
- * @var string
- * @access private
- */
- var $_realname;
-
- /**
- * @var string
- * @access private
- */
- var $_usermode;
-
- /**
- * @var string
- * @access private
- */
- var $_password;
-
- /**
- * @var boolean
- * @access private
- */
- var $_state = false;
-
- /**
- * @var array
- * @access private
- */
- var $_actionhandler = array();
-
- /**
- * @var array
- * @access private
- */
- var $_timehandler = array();
-
- /**
- * @var integer
- * @access private
- */
- var $_debug = SMARTIRC_DEBUG_NOTICE;
-
- /**
- * @var array
- * @access private
- */
- var $_messagebuffer = array();
-
- /**
- * @var integer
- * @access private
- */
- var $_messagebuffersize;
-
- /**
- * @var boolean
- * @access private
- */
- var $_usesockets = false;
-
- /**
- * @var integer
- * @access private
- */
- var $_receivedelay = 100;
-
- /**
- * @var integer
- * @access private
- */
- var $_senddelay = 250;
-
- /**
- * @var integer
- * @access private
- */
- var $_logdestination = SMARTIRC_STDOUT;
-
- /**
- * @var resource
- * @access private
- */
- var $_logfilefp = 0;
-
- /**
- * @var string
- * @access private
- */
- var $_logfile = 'Net_SmartIRC.log';
-
- /**
- * @var integer
- * @access private
- */
- var $_disconnecttime = 1000;
-
- /**
- * @var boolean
- * @access private
- */
- var $_loggedin = false;
-
- /**
- * @var boolean
- * @access private
- */
- var $_benchmark = false;
-
- /**
- * @var integer
- * @access private
- */
- var $_benchmark_starttime;
-
- /**
- * @var integer
- * @access private
- */
- var $_benchmark_stoptime;
-
- /**
- * @var integer
- * @access private
- */
- var $_actionhandlerid = 0;
-
- /**
- * @var integer
- * @access private
- */
- var $_timehandlerid = 0;
-
- /**
- * @var array
- * @access private
- */
- var $_motd = array();
-
- /**
- * @var array
- * @access private
- */
- var $_channels = array();
-
- /**
- * @var boolean
- * @access private
- */
- var $_channelsyncing = false;
-
- /**
- * @var string
- * @access private
- */
- var $_ctcpversion;
-
- /**
- * @var mixed
- * @access private
- */
- var $_mintimer = false;
-
- /**
- * @var integer
- * @access private
- */
- var $_maxtimer = 300000;
-
- /**
- * @var integer
- * @access private
- */
- var $_txtimeout = 300;
-
- /**
- * @var integer
- * @access private
- */
- var $_rxtimeout = 300;
-
- /**
- * @var integer
- * @access private
- */
- var $_selecttimeout;
-
- /**
- * @var integer
- * @access private
- */
- var $_lastrx;
-
- /**
- * @var integer
- * @access private
- */
- var $_lasttx;
-
- /**
- * @var boolean
- * @access private
- */
- var $_autoreconnect = false;
-
- /**
- * @var boolean
- * @access private
- */
- var $_autoretry = false;
-
- /**
- * All IRC replycodes, the index is the replycode name.
- *
- * @see $SMARTIRC_replycodes
- * @var array
- * @access public
- */
- var $replycodes;
-
- /**
- * All numeric IRC replycodes, the index is the numeric replycode.
- *
- * @see $SMARTIRC_nreplycodes
- * @var array
- * @access public
- */
- var $nreplycodes;
-
- /**
- * Stores all channels in this array where we are joined, works only if channelsyncing is activated.
- * Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
- * $irc->channel['#test']->users['meebey']->nick;
- *
- * @see setChannelSyncing()
- * @see Net_SmartIRC_channel
- * @see Net_SmartIRC_channeluser
- * @var array
- * @access public
- */
- var $channel;
-
- /**
- * Constructor. Initiales the messagebuffer and "links" the replycodes from
- * global into properties. Also some PHP runtime settings are configured.
- *
- * @access public
- * @return void
- */
- function Net_SmartIRC_base()
- {
- // precheck
- $this->_checkPHPVersion();
-
- ob_implicit_flush(true);
- @set_time_limit(0);
- ignore_user_abort(true);
- $this->_messagebuffer[SMARTIRC_CRITICAL] = array();
- $this->_messagebuffer[SMARTIRC_HIGH] = array();
- $this->_messagebuffer[SMARTIRC_MEDIUM] = array();
- $this->_messagebuffer[SMARTIRC_LOW] = array();
- $this->replycodes = &$GLOBALS['SMARTIRC_replycodes'];
- $this->nreplycodes = &$GLOBALS['SMARTIRC_nreplycodes'];
-
- // hack till PHP allows (PHP5) $object->method($param)->$object
- $this->channel = &$this->_channels;
- // another hack
- $this->user = &$this->_users;
-
- if (isset($_SERVER['REQUEST_METHOD'])) {
- // the script is called from a browser, lets set default log destination
- // to SMARTIRC_BROWSEROUT (makes browser friendly output)
- $this->setLogdestination(SMARTIRC_BROWSEROUT);
- }
- }
-
- /**
- * Enables/disables the usage of real sockets.
- *
- * Enables/disables the usage of real sockets instead of fsocks
- * (works only if your PHP build has loaded the PHP socket extension)
- * Default: false
- *
- * @param bool $boolean
- * @return void
- * @access public
- */
- function setUseSockets($boolean)
- {
- if ($boolean === true) {
- if (@extension_loaded('sockets')) {
- $this->_usesockets = true;
- } else {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket extension not loaded, trying to load it...', __FILE__, __LINE__);
-
- if (strtoupper(substr(PHP_OS, 0,3) == 'WIN')) {
- $load_status = @dl('php_sockets.dll');
- } else {
- $load_status = @dl('sockets.so');
- }
-
- if ($load_status) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket extension succesfully loaded', __FILE__, __LINE__);
- $this->_usesockets = true;
- } else {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: couldn\'t load the socket extension', __FILE__, __LINE__);
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: your PHP build doesn\'t support real sockets, will use fsocks instead', __FILE__, __LINE__);
- $this->_usesockets = false;
- }
- }
- } else {
- $this->_usesockets = false;
- }
- }
-
- /**
- * Sets the level of debug messages.
- *
- * Sets the debug level (bitwise), useful for testing/developing your code.
- * Here the list of all possible debug levels:
- * SMARTIRC_DEBUG_NONE
- * SMARTIRC_DEBUG_NOTICE
- * SMARTIRC_DEBUG_CONNECTION
- * SMARTIRC_DEBUG_SOCKET
- * SMARTIRC_DEBUG_IRCMESSAGES
- * SMARTIRC_DEBUG_MESSAGETYPES
- * SMARTIRC_DEBUG_ACTIONHANDLER
- * SMARTIRC_DEBUG_TIMEHANDLER
- * SMARTIRC_DEBUG_MESSAGEHANDLER
- * SMARTIRC_DEBUG_CHANNELSYNCING
- * SMARTIRC_DEBUG_MODULES
- * SMARTIRC_DEBUG_USERSYNCING
- * SMARTIRC_DEBUG_ALL
- *
- * Default: SMARTIRC_DEBUG_NOTICE
- *
- * @see DOCUMENTATION
- * @see SMARTIRC_DEBUG_NOTICE
- * @param integer $level
- * @return void
- * @access public
- */
- function setDebug($level)
- {
- $this->_debug = $level;
- }
-
- /**
- * Enables/disables the benchmark engine.
- *
- * @param boolean $boolean
- * @return void
- * @access public
- */
- function setBenchmark($boolean)
- {
- if (is_bool($boolean)) {
- $this->_benchmark = $boolean;
- } else {
- $this->_benchmark = false;
- }
- }
-
- /**
- * Deprecated, use setChannelSyncing() instead!
- *
- * @deprecated
- * @param boolean $boolean
- * @return void
- * @access public
- */
- function setChannelSynching($boolean)
- {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: you are using setChannelSynching() which is a deprecated method, use setChannelSyncing() instead!', __FILE__, __LINE__);
- $this->setChannelSyncing($boolean);
- }
-
- /**
- * Enables/disables channel syncing.
- *
- * Channel syncing means, all users on all channel we are joined are tracked in the
- * channel array. This makes it very handy for botcoding.
- *
- * @param boolean $boolean
- * @return void
- * @access public
- */
- function setChannelSyncing($boolean)
- {
- if (is_bool($boolean)) {
- $this->_channelsyncing = $boolean;
- } else {
- $this->_channelsyncing = false;
- }
-
- if ($this->_channelsyncing == true) {
- $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: Channel syncing enabled', __FILE__, __LINE__);
- } else {
- $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: Channel syncing disabled', __FILE__, __LINE__);
- }
- }
-
- /**
- * Sets the CTCP version reply string.
- *
- * @param string $versionstring
- * @return void
- * @access public
- */
- function setCtcpVersion($versionstring)
- {
- $this->_ctcpversion = $versionstring;
- }
-
- /**
- * Sets the destination of all log messages.
- *
- * Sets the destination of log messages.
- * $type can be:
- * SMARTIRC_FILE for saving the log into a file
- * SMARTIRC_STDOUT for echoing the log to stdout
- * SMARTIRC_SYSLOG for sending the log to the syslog
- * Default: SMARTIRC_STDOUT
- *
- * @see SMARTIRC_STDOUT
- * @param integer $type must be on of the constants
- * @return void
- * @access public
- */
- function setLogdestination($type)
- {
- switch ($type) {
- case (SMARTIRC_FILE ||
- SMARTIRC_STDOUT ||
- SMARTIRC_SYSLOG ||
- SMARTIRC_BROWSEROUT ||
- SMARTIRC_NONE):
- $this->_logdestination = $type;
- break;
- default:
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: unknown logdestination type ('.$type.'), will use STDOUT instead', __FILE__, __LINE__);
- $this->_logdestination = SMARTIRC_STDOUT;
- }
- }
-
- /**
- * Sets the file for the log if the destination is set to file.
- *
- * Sets the logfile, if {@link setLogdestination logdestination} is set to SMARTIRC_FILE.
- * This should be only used with full path!
- *
- * @param string $file
- * @return void
- * @access public
- */
- function setLogfile($file)
- {
- $this->_logfile = $file;
- }
-
- /**
- * Sets the delaytime before closing the socket when disconnect.
- *
- * @param integer $milliseconds
- * @return void
- * @access public
- */
- function setDisconnecttime($milliseconds)
- {
- if (is_integer($milliseconds) && $milliseconds >= 100) {
- $this->_disconnecttime = $milliseconds;
- } else {
- $this->_disconnecttime = 100;
- }
- }
-
- /**
- * Sets the delay for receiving data from the IRC server.
- *
- * Sets the delaytime between messages that are received, this reduces your CPU load.
- * Don't set this too low (min 100ms).
- * Default: 100
- *
- * @param integer $milliseconds
- * @return void
- * @access public
- */
- function setReceivedelay($milliseconds)
- {
- if (is_integer($milliseconds) && $milliseconds >= 100) {
- $this->_receivedelay = $milliseconds;
- } else {
- $this->_receivedelay = 100;
- }
- }
-
- /**
- * Sets the delay for sending data to the IRC server.
- *
- * Sets the delaytime between messages that are sent, because IRC servers doesn't like floods.
- * This will avoid sending your messages too fast to the IRC server.
- * Default: 250
- *
- * @param integer $milliseconds
- * @return void
- * @access public
- */
- function setSenddelay($milliseconds)
- {
- if (is_integer($milliseconds)) {
- $this->_senddelay = $milliseconds;
- } else {
- $this->_senddelay = 250;
- }
- }
-
- /**
- * Enables/disables autoreconnecting.
- *
- * @param boolean $boolean
- * @return void
- * @access public
- */
- function setAutoReconnect($boolean)
- {
- if (is_bool($boolean)) {
- $this->_autoreconnect = $boolean;
- } else {
- $this->_autoreconnect = false;
- }
- }
-
- /**
- * Enables/disables autoretry for connecting to a server.
- *
- * @param boolean $boolean
- * @return void
- * @access public
- */
- function setAutoRetry($boolean)
- {
- if (is_bool($boolean)) {
- $this->_autoretry = $boolean;
- } else {
- $this->_autoretry = false;
- }
- }
-
- /**
- * Sets the receive timeout.
- *
- * If the timeout occurs, the connection will be reinitialized
- * Default: 300 seconds
- *
- * @param integer $seconds
- * @return void
- * @access public
- */
- function setReceiveTimeout($seconds)
- {
- if (is_integer($seconds)) {
- $this->_rxtimeout = $seconds;
- } else {
- $this->_rxtimeout = 300;
- }
- }
-
- /**
- * Sets the transmit timeout.
- *
- * If the timeout occurs, the connection will be reinitialized
- * Default: 300 seconds
- *
- * @param integer $seconds
- * @return void
- * @access public
- */
- function setTransmitTimeout($seconds)
- {
- if (is_integer($seconds)) {
- $this->_txtimeout = $seconds;
- } else {
- $this->_txtimeout = 300;
- }
- }
-
- /**
- * Starts the benchmark (sets the counters).
- *
- * @return void
- * @access public
- */
- function startBenchmark()
- {
- $this->_benchmark_starttime = $this->_microint();
- $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark started', __FILE__, __LINE__);
- }
-
- /**
- * Stops the benchmark and displays the result.
- *
- * @return void
- * @access public
- */
- function stopBenchmark()
- {
- $this->_benchmark_stoptime = $this->_microint();
- $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark stopped', __FILE__, __LINE__);
-
- if ($this->_benchmark) {
- $this->showBenchmark();
- }
- }
-
- /**
- * Shows the benchmark result.
- *
- * @return void
- * @access public
- */
- function showBenchmark()
- {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark time: '.((float)$this->_benchmark_stoptime-(float)$this->_benchmark_starttime), __FILE__, __LINE__);
- }
-
- /**
- * Adds an entry to the log.
- *
- * Adds an entry to the log with Linux style log format.
- * Possible $level constants (can also be combined with "|"s)
- * SMARTIRC_DEBUG_NONE
- * SMARTIRC_DEBUG_NOTICE
- * SMARTIRC_DEBUG_CONNECTION
- * SMARTIRC_DEBUG_SOCKET
- * SMARTIRC_DEBUG_IRCMESSAGES
- * SMARTIRC_DEBUG_MESSAGETYPES
- * SMARTIRC_DEBUG_ACTIONHANDLER
- * SMARTIRC_DEBUG_TIMEHANDLER
- * SMARTIRC_DEBUG_MESSAGEHANDLER
- * SMARTIRC_DEBUG_CHANNELSYNCING
- * SMARTIRC_DEBUG_MODULES
- * SMARTIRC_DEBUG_USERSYNCING
- * SMARTIRC_DEBUG_ALL
- *
- * @see SMARTIRC_DEBUG_NOTICE
- * @param integer $level bit constants (SMARTIRC_DEBUG_*)
- * @param string $entry the new log entry
- * @return void
- * @access public
- */
- function log($level, $entry, $file = null, $line = null)
- {
- // prechecks
- if (!(is_integer($level)) ||
- !($level & SMARTIRC_DEBUG_ALL)) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: invalid log level passed to log() ('.$level.')', __FILE__, __LINE__);
- return;
- }
-
- if (!($level & $this->_debug) ||
- ($this->_logdestination == SMARTIRC_NONE)) {
- return;
- }
-
- if (substr($entry, -1) != "\n") {
- $entry .= "\n";
- }
-
- if ($file !== null &&
- $line !== null) {
- $file = basename($file);
- $entry = $file.'('.$line.') '.$entry;
- } else {
- $entry = 'unknown(0) '.$entry;
- }
-
- $formatedentry = date('M d H:i:s ').$entry;
- switch ($this->_logdestination) {
- case SMARTIRC_STDOUT:
- echo $formatedentry;
- flush();
- break;
- case SMARTIRC_BROWSEROUT:
- echo '<pre>'.htmlentities($formatedentry).'</pre>';
- break;
- case SMARTIRC_FILE:
- if (!is_resource($this->_logfilefp)) {
- if ($this->_logfilefp === null) {
- // we reconncted and don't want to destroy the old log entries
- $this->_logfilefp = @fopen($this->_logfile,'a');
- } else {
- $this->_logfilefp = @fopen($this->_logfile,'w');
- }
- }
- @fwrite($this->_logfilefp, $formatedentry);
- fflush($this->_logfilefp);
- break;
- case SMARTIRC_SYSLOG:
- define_syslog_variables();
- if (!is_int($this->_logfilefp)) {
- $this->_logfilefp = openlog('Net_SmartIRC', LOG_NDELAY, LOG_DAEMON);
- }
- syslog(LOG_INFO, $entry);
- break;
- }
- }
-
- /**
- * Returns the full motd.
- *
- * @return array
- * @access public
- */
- function getMotd()
- {
- return $this->_motd;
- }
-
- /**
- * Returns the usermode.
- *
- * @return string
- * @access public
- */
- function getUsermode()
- {
- return $this->_usermode;
- }
-
- /**
- * Creates the sockets and connects to the IRC server on the given port.
- *
- * @param string $address
- * @param integer $port
- * @return void
- * @access public
- */
- function connect($address, $port)
- {
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connecting', __FILE__, __LINE__);
- $this->_address = $address;
- $this->_port = $port;
-
- if ($this->_usesockets == true) {
- $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: using real sockets', __FILE__, __LINE__);
- $this->_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
- $result = @socket_connect($this->_socket, $this->_address, $this->_port);
- } else {
- $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: using fsockets', __FILE__, __LINE__);
- $result = @fsockopen($this->_address, $this->_port, $errno, $errstr);
- }
-
- if ($result === false) {
- if ($this->_usesockets == true) {
- $error = socket_strerror(socket_last_error($this->_socket));
- } else {
- $error = $errstr.' ('.$errno.')';
- }
-
- $error_msg = 'couldn\'t connect to "'.$address.'" reason: "'.$error.'"';
- $this->log(SMARTIRC_DEBUG_NOTICE, 'DEBUG_NOTICE: '.$error_msg, __FILE__, __LINE__);
- // TODO! muss return wert sein
- $this->throwError($error_msg);
-
- // doesn't work somehow.... I only want to retry 4 times! no endless loop (causes segfault)
- static $tries = 0;
- if ($this->_autoretry == true && $tries < 5) {
- $this->reconnect();
- $tries++;
- } else {
- die();
- }
- } else {
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connected', __FILE__, __LINE__);
-
- if ($this->_usesockets != true) {
- $this->_socket = $result;
- $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: activating nonblocking fsocket mode', __FILE__, __LINE__);
- socket_set_blocking($this->_socket, false);
- }
- }
-
- $this->_lastrx = time();
- $this->_lasttx = $this->_lastrx;
- $this->_updatestate();
-
- if ($result !== false) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Disconnects from the IRC server nicely with a QUIT or just destroys the socket.
- *
- * Disconnects from the IRC server in the given quickness mode.
- * $quickdisconnect:
- * true, just close the socket
- * false, send QUIT and wait {@link $_disconnectime $_disconnectime} before closing the socket
- *
- * @param boolean $quickdisconnect default: false
- * @return boolean
- * @access public
- */
- function disconnect($quickdisconnect = false)
- {
- if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
- if ($quickdisconnect == false) {
- $this->_send('QUIT', SMARTIRC_CRITICAL);
- usleep($this->_disconnecttime*1000);
- }
-
- if ($this->_usesockets == true) {
- @socket_shutdown($this->_socket);
- @socket_close($this->_socket);
- } else {
- fclose($this->_socket);
- }
-
- $this->_updatestate();
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: disconnected', __FILE__, __LINE__);
- } else {
- return false;
- }
-
- if ($this->_channelsyncing == true) {
- // let's clean our channel array
- $this->_channels = array();
- $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: cleaned channel array', __FILE__, __LINE__);
- }
-
- if ($this->_logdestination == SMARTIRC_FILE) {
- fclose($this->_logfilefp);
- $this->_logfilefp = null;
- } else if ($this->_logdestination == SMARTIRC_SYSLOG) {
- closelog();
- }
-
- return true;
- }
-
- /**
- * Reconnects to the IRC server with the same login info,
- * it also rejoins the channels
- *
- * @return void
- * @access public
- */
- function reconnect()
- {
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: reconnecting...', __FILE__, __LINE__);
-
- // remember in which channels we are joined
- $channels = array();
- foreach ($this->_channels as $value) {
- if (empty($value->key)) {
- $channels[] = array('name' => $value->name);
- } else {
- $channels[] = array('name' => $value->name, 'key' => $value->key);
- }
- }
-
- $this->disconnect(true);
- $this->connect($this->_address, $this->_port);
- $this->login($this->_nick, $this->_realname, $this->_usermode, $this->_username, $this->_password);
-
- // rejoin the channels
- foreach ($channels as $value) {
- if (isset($value['key'])) {
- $this->join($value['name'], $value['key']);
- } else {
- $this->join($value['name']);
- }
- }
- }
-
- /**
- * login and register nickname on the IRC network
- *
- * Registers the nickname and user information on the IRC network.
- *
- * @param string $nick
- * @param string $realname
- * @param integer $usermode
- * @param string $username
- * @param string $password
- * @return void
- * @access public
- */
- function login($nick, $realname, $usermode = 0, $username = null, $password = null)
- {
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: logging in', __FILE__, __LINE__);
-
- $this->_nick = str_replace(' ', '', $nick);
- $this->_realname = $realname;
-
- if ($username !== null) {
- $this->_username = str_replace(' ', '', $username);
- } else {
- $this->_username = str_replace(' ', '', exec('whoami'));
- }
-
- if ($password !== null) {
- $this->_password = $password;
- $this->_send('PASS '.$this->_password, SMARTIRC_CRITICAL);
- }
-
- if (!is_numeric($usermode)) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'DEBUG_NOTICE: login() usermode ('.$usermode.') is not valid, will use 0 instead', __FILE__, __LINE__);
- $usermode = 0;
- }
-
- $this->_send('NICK '.$this->_nick, SMARTIRC_CRITICAL);
- $this->_send('USER '.$this->_username.' '.$usermode.' '.SMARTIRC_UNUSED.' :'.$this->_realname, SMARTIRC_CRITICAL);
- }
-
- // </IRC methods>
-
- /**
- * checks if we or the given user is joined to the specified channel and returns the result
- * ChannelSyncing is required for this.
- *
- * @see setChannelSyncing
- * @param string $channel
- * @param string $nickname
- * @return boolean
- * @access public
- */
- function isJoined($channel, $nickname = null)
- {
- if ($this->_channelsyncing != true) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isJoined() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
- return false;
- }
-
- if ($nickname === null) {
- $nickname = $this->_nick;
- }
-
- if (isset($this->_channels[strtolower($channel)]->users[strtolower($nickname)])) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Checks if we or the given user is opped on the specified channel and returns the result.
- * ChannelSyncing is required for this.
- *
- * @see setChannelSyncing
- * @param string $channel
- * @param string $nickname
- * @return boolean
- * @access public
- */
- function isOpped($channel, $nickname = null)
- {
- if ($this->_channelsyncing != true) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isOpped() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
- return false;
- }
-
- if ($nickname === null) {
- $nickname = $this->_nick;
- }
-
- if ($this->isJoined($channel, $nickname)) {
- if ($this->_channels[strtolower($channel)]->users[strtolower($nickname)]->op) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Checks if we or the given user is voiced on the specified channel and returns the result.
- * ChannelSyncing is required for this.
- *
- * @see setChannelSyncing
- * @param string $channel
- * @param string $nickname
- * @return boolean
- * @access public
- */
- function isVoiced($channel, $nickname = null)
- {
- if ($this->_channelsyncing != true) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isVoiced() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
- return false;
- }
-
- if ($nickname === null) {
- $nickname = $this->_nick;
- }
-
- if ($this->isJoined($channel, $nickname)) {
- if ($this->_channels[strtolower($channel)]->users[strtolower($nickname)]->voice) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Checks if the hostmask is on the specified channel banned and returns the result.
- * ChannelSyncing is required for this.
- *
- * @see setChannelSyncing
- * @param string $channel
- * @param string $hostmask
- * @return boolean
- * @access public
- */
- function isBanned($channel, $hostmask)
- {
- if ($this->_channelsyncing != true) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isBanned() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
- return false;
- }
-
- if ($this->isJoined($channel)) {
- $result = array_search($hostmask, $this->_channels[strtolower($channel)]->bans);
-
- if ($result !== false) {
- return true;
- }
- }
-
- return false;
- }
- /**
- * goes into receive mode
- *
- * Goes into receive and idle mode. Only call this if you want to "spawn" the bot.
- * No further lines of PHP code will be processed after this call, only the bot methods!
- *
- * @return boolean
- * @access public
- */
- function listen()
- {
- if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
- $this->_rawreceive();
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * waits for a special message type and puts the answer in $result
- *
- * Creates a special actionhandler for that given TYPE and returns the answer.
- * This will only receive the requested type, immediately quit and disconnect from the IRC server.
- * Made for showing IRC statistics on your homepage, or other IRC related information.
- *
- * @param integer $messagetype see in the documentation 'Message Types'
- * @return array answer from the IRC server for this $messagetype
- * @access public
- */
- function listenFor($messagetype)
- {
- $listenfor = &new Net_SmartIRC_listenfor();
- $this->registerActionhandler($messagetype, '.*', $listenfor, 'handler');
- $this->listen();
- $result = $listenfor->result;
-
- if (isset($listenfor)) {
- unset($listenfor);
- }
-
- return $result;
- }
-
- /**
- * waits for a special message type and puts the answer in $result
- *
- * Creates a special actionhandler for that given TYPE and returns the answer.
- * This will only receive the requested type, immediately quit and disconnect from the IRC server.
- * Made for showing IRC statistics on your homepage, or other IRC related information.
- * This special version of listenFor() stores the whole ircdata object, not just the message!
- *
- * @param integer $messagetype see in the documentation 'Message Types'
- * @return array answer from the IRC server for this $messagetype
- * @access public
- */
- function objListenFor($messagetype)
- {
- $objlistenfor = &new Net_SmartIRC_objListenFor();
- $this->registerActionhandler($messagetype, '.*', $objlistenfor, 'handler');
- $this->listen();
- $result = $objlistenfor->result;
-
- if (isset($objlistenfor)) {
- unset($objlistenfor);
- }
-
- return $result;
- }
-
- /**
- * registers a new actionhandler and returns the assigned id
- *
- * Registers an actionhandler in Net_SmartIRC for calling it later.
- * The actionhandler id is needed for unregistering the actionhandler.
- *
- * @see example.php
- * @param integer $handlertype bits constants, see in this documentation Message Types
- * @param string $regexhandler the message that has to be in the IRC message in regex syntax
- * @param object $object a reference to the objects of the method
- * @param string $methodname the methodname that will be called when the handler happens
- * @return integer assigned actionhandler id
- * @access public
- */
- function registerActionhandler($handlertype, $regexhandler, &$object, $methodname)
- {
- // precheck
- if (!$this->_isValidType($handlertype)) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: passed invalid handlertype to registerActionhandler()', __FILE__, __LINE__);
- return false;
- }
-
- $id = $this->_actionhandlerid++;
- $newactionhandler = &new Net_SmartIRC_actionhandler();
-
- $newactionhandler->id = $id;
- $newactionhandler->type = $handlertype;
- $newactionhandler->message = $regexhandler;
- $newactionhandler->object = &$object;
- $newactionhandler->method = $methodname;
-
- $this->_actionhandler[] = &$newactionhandler;
- $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') registered', __FILE__, __LINE__);
- return $id;
- }
-
- /**
- * unregisters an existing actionhandler
- *
- * @param integer $handlertype
- * @param string $regexhandler
- * @param object $object
- * @param string $methodname
- * @return boolean
- * @access public
- */
- function unregisterActionhandler($handlertype, $regexhandler, &$object, $methodname)
- {
- // precheck
- if (!$this->_isValidType($handlertype)) {
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: passed invalid handlertype to unregisterActionhandler()', __FILE__, __LINE__);
- return false;
- }
-
- $handler = &$this->_actionhandler;
- $handlercount = count($handler);
-
- for ($i = 0; $i < $handlercount; $i++) {
- $handlerobject = &$handler[$i];
-
- if ($handlerobject->type == $handlertype &&
- $handlerobject->message == $regexhandler &&
- $handlerobject->method == $methodname) {
-
- $id = $handlerobject->id;
-
- if (isset($this->_actionhandler[$i])) {
- unset($this->_actionhandler[$i]);
- }
-
- $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') unregistered', __FILE__, __LINE__);
- $this->_reorderactionhandler();
- return true;
- }
- }
-
- $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__);
- return false;
- }
-
- /**
- * unregisters an existing actionhandler via the id
- *
- * @param integer $id
- * @return boolean
- * @access public
- */
- function unregisterActionid($id)
- {
- $handler = &$this->_actionhandler;
- $handlercount = count($handler);
- for ($i = 0; $i < $handlercount; $i++) {
- $handlerobject = &$handler[$i];
-
- if ($handlerobject->id == $id) {
- if (isset($this->_actionhandler[$i])) {
- unset($this->_actionhandler[$i]);
- }
-
- $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') unregistered', __FILE__, __LINE__);
- $this->_reorderactionhandler();
- return true;
- }
- }
-
- $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: could not find actionhandler id: '.$id.' _not_ unregistered', __FILE__, __LINE__);
- return false;
- }
-
- /**
- * registers a timehandler and returns the assigned id
- *
- * Registers a timehandler in Net_SmartIRC, which will be called in the specified interval.
- * The timehandler id is needed for unregistering the timehandler.
- *
- * @see example7.php
- * @param integer $interval interval time in milliseconds
- * @param object $object a reference to the objects of the method
- * @param string $methodname the methodname that will be called when the handler happens
- * @return integer assigned timehandler id
- * @access public
- */
- function registerTimehandler($interval, &$object, $methodname)
- {
- $id = $this->_timehandlerid++;
- $newtimehandler = &new Net_SmartIRC_timehandler();
-
- $newtimehandler->id = $id;
- $newtimehandler->interval = $interval;
- $newtimehandler->object = &$object;
- $newtimehandler->method = $methodname;
- $newtimehandler->lastmicrotimestamp = $this->_microint();
-
- $this->_timehandler[] = &$newtimehandler;
- $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: timehandler('.$id.') registered', __FILE__, __LINE__);
-
- if (($interval < $this->_mintimer) || ($this->_mintimer == false)) {
- $this->_mintimer = $interval;
- }
-
- return $id;
- }
-
- /**
- * unregisters an existing timehandler via the id
- *
- * @see example7.php
- * @param integer $id
- * @return boolean
- * @access public
- */
- function unregisterTimeid($id)
- {
- $handler = &$this->_timehandler;
- $handlercount = count($handler);
- for ($i = 0; $i < $handlercount; $i++) {
- $handlerobject = &$handler[$i];
-
- if ($handlerobject->id == $id) {
- if (isset($this->_timehandler[$i])) {
- unset($this->_timehandler[$i]);
- }
-
- $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: timehandler('.$id.') unregistered', __FILE__, __LINE__);
- $this->_reordertimehandler();
- $this->_updatemintimer();
- return true;
- }
- }
-
- $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: could not find timehandler id: '.$id.' _not_ unregistered', __FILE__, __LINE__);
- return false;
- }
-
- // <private methods>
- /**
- * changes a already used nickname to a new nickname plus 3 random digits
- *
- * @return void
- * @access private
- */
- function _nicknameinuse()
- {
- $newnickname = substr($this->_nick, 0, 5).rand(0, 999);
- $this->changeNick($newnickname, SMARTIRC_CRITICAL);
- }
-
- /**
- * sends an IRC message
- *
- * Adds a message to the messagequeue, with the optional priority.
- * $priority:
- * SMARTIRC_CRITICAL
- * SMARTIRC_HIGH
- * SMARTIRC_MEDIUM
- * SMARTIRC_LOW
- *
- * @param string $data
- * @param integer $priority must be one of the priority constants
- * @return boolean
- * @access private
- */
- function _send($data, $priority = SMARTIRC_MEDIUM)
- {
- switch ($priority) {
- case SMARTIRC_CRITICAL:
- $this->_rawsend($data);
- return true;
- break;
- case (SMARTIRC_HIGH||
- SMARTIRC_MEDIUM||
- SMARTIRC_LOW):
- $this->_messagebuffer[$priority][] = $data;
- return true;
- break;
- default:
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: message ('.$data.') with an invalid priority passed ('.$priority.'), message is ignored!', __FILE__, __LINE__);
- return false;
- }
- }
-
- /**
- * checks the buffer if there are messages to send
- *
- * @return void
- * @access private
- */
- function _checkbuffer()
- {
- if (!$this->_loggedin) {
- return;
- }
-
- static $highsent = 0;
- static $lastmicrotimestamp = 0;
-
- if ($lastmicrotimestamp == 0) {
- $lastmicrotimestamp = $this->_microint();
- }
-
- $highcount = count($this->_messagebuffer[SMARTIRC_HIGH]);
- $mediumcount = count($this->_messagebuffer[SMARTIRC_MEDIUM]);
- $lowcount = count($this->_messagebuffer[SMARTIRC_LOW]);
- $this->_messagebuffersize = $highcount+$mediumcount+$lowcount;
-
- // don't send them too fast
- if ($this->_microint() >= ($lastmicrotimestamp+($this->_senddelay/1000))) {
- if ($highcount > 0 && $highsent <= 2) {
- $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_HIGH]));
- $lastmicrotimestamp = $this->_microint();
- $highsent++;
- } else if ($mediumcount > 0) {
- $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_MEDIUM]));
- $lastmicrotimestamp = $this->_microint();
- $highsent = 0;
- } else if ($lowcount > 0) {
- $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_LOW]));
- $lastmicrotimestamp = $this->_microint();
- }
- }
- }
-
- /**
- * Checks the running timers and calls the registered timehandler,
- * when the interval is reached.
- *
- * @return void
- * @access private
- */
- function _checktimer()
- {
- if (!$this->_loggedin) {
- return;
- }
-
- // has to be count() because the array may change during the loop!
- for ($i = 0; $i < count($this->_timehandler); $i++) {
- $handlerobject = &$this->_timehandler[$i];
- $microtimestamp = $this->_microint();
- if ($microtimestamp >= ($handlerobject->lastmicrotimestamp+($handlerobject->interval/1000))) {
- $methodobject = &$handlerobject->object;
- $method = $handlerobject->method;
- $handlerobject->lastmicrotimestamp = $microtimestamp;
-
- if (@method_exists($methodobject, $method)) {
- $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: calling method "'.get_class($methodobject).'->'.$method.'"', __FILE__, __LINE__);
- $methodobject->$method($this);
- }
- }
- }
- }
-
- /**
- * Checks if a receive or transmit timeout occured and reconnects if configured
- *
- * @return void
- * @access private
- */
- function _checktimeout()
- {
- if ($this->_autoreconnect == true) {
- $timestamp = time();
- if ($this->_lastrx < ($timestamp - $this->_rxtimeout)) {
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: receive timeout detected, doing reconnect...', __FILE__, __LINE__);
- $this->reconnect();
- } else if ($this->_lasttx < ($timestamp - $this->_txtimeout)) {
- $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: transmit timeout detected, doing reconnect...', __FILE__, __LINE__);
- $this->reconnect();
- }
- }
- }
-
- /**
- * sends a raw message to the IRC server (don't use this!!)
- *
- * Use message() or _send() instead.
- *
- * @param string $data
- * @return boolean
- * @access private
- */
- function _rawsend($data)
- {
- if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
- $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: sent: "'.$data.'"', __FILE__, __LINE__);
-
- if ($this->_usesockets == true) {
- $result = @socket_write($this->_socket, $data.SMARTIRC_CRLF);
- } else {
- $result = @fwrite($this->_socket, $data.SMARTIRC_CRLF);
- }
-
-
- if ($result === false) {
- return false;
- } else {
- $this->_lasttx = time();
- return true;
- }
- } else {
- return false;
- }
- }
-
- /**
- * goes into main idle loop for waiting messages from the IRC server
- *
- * @return void
- * @access private
- */
- function _rawreceive()
- {
- $lastpart = '';
- $rawdataar = array();
-
- while ($this->_state() == SMARTIRC_STATE_CONNECTED) {
- $this->_checkbuffer();
-
- $timeout = $this->_selecttimeout();
- if ($this->_usesockets == true) {
- $sread = array($this->_socket);
- $result = @socket_select($sread, $w = null, $e = null, 0, $timeout*1000);
-
- if ($result == 1) {
- // the socket got data to read
- $rawdata = @socket_read($this->_socket, 10240);
- } else if ($result === false) {
- // panic! panic! something went wrong!
- $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket_select() returned false, something went wrong! Reason: '.socket_strerror(socket_last_error()), __FILE__, __LINE__);
- exit;
- } else {
- // no data
- $rawdata = null;
- }
- } else {
- usleep($this->_receivedelay*1000);
- $rawdata = @fread($this->_socket, 10240);
- }
-
- $this->_checktimer();
- $this->_checktimeout();
-
- if ($rawdata !== null && !empty($rawdata)) {
- $this->_lastrx = time();
- $rawdata = str_replace("\r", '', $rawdata);
- $rawdata = $lastpart.$rawdata;
-
- $lastpart = substr($rawdata, strrpos($rawdata ,"\n")+1);
- $rawdata = substr($rawdata, 0, strrpos($rawdata ,"\n"));
- $rawdataar = explode("\n", $rawdata);
- }
-
- // loop through our received messages
- while (count($rawdataar) > 0) {
- $rawline = array_shift($rawdataar);
- $validmessage = false;
-
- $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: received: "'.$rawline.'"', __FILE__, __LINE__);
-
- // building our data packet
- $ircdata = &new Net_SmartIRC_data();
- $ircdata->rawmessage = $rawline;
- $lineex = explode(' ', $rawline);
- $ircdata->rawmessageex = $lineex;
- $messagecode = $lineex[0];
-
- if (substr($rawline, 0, 1) == ':') {
- $validmessage = true;
- $line = substr($rawline, 1);
- $lineex = explode(' ', $line);
-
- // conform to RFC 2812
- $from = $lineex[0];
- $messagecode = $lineex[1];
- $exclamationpos = strpos($from, '!');
- $atpos = strpos($from, '@');
- $colonpos = strpos($line, ' :');
- if ($colonpos !== false) {
- // we want the exact position of ":" not beginning from the space
- $colonpos += 1;
- }
- $ircdata->nick = substr($from, 0, $exclamationpos);
- $ircdata->ident = substr($from, $exclamationpos+1, ($atpos-$exclamationpos)-1);
- $ircdata->host = substr($from, $atpos+1);
- $ircdata->type = $this->_gettype($rawline);
- $ircdata->from = $from;
- if ($colonpos !== false) {
- $ircdata->message = substr($line, $…
Large files files are truncated, but you can click here to view the full file