PageRenderTime 60ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/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
Possible License(s): Apache-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-2-Clause, GPL-2.0, LGPL-3.0
  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 ----------
  46. include_once('SmartIRC/defines.php');
  47. include_once('SmartIRC/irccommands.php');
  48. include_once('SmartIRC/messagehandler.php');
  49. define('SMARTIRC_VERSION', '1.0.0 ($Revision: 1.54.2.14 $)');
  50. define('SMARTIRC_VERSIONSTRING', 'Net_SmartIRC '.SMARTIRC_VERSION);
  51. /**
  52. * main SmartIRC class
  53. *
  54. * @package Net_SmartIRC
  55. * @version 0.5.5
  56. * @author Mirco 'meebey' Bauer <mail@meebey.net>
  57. * @access public
  58. */
  59. class Net_SmartIRC_base
  60. {
  61. /**
  62. * @var resource
  63. * @access private
  64. */
  65. var $_socket;
  66. /**
  67. * @var string
  68. * @access private
  69. */
  70. var $_address;
  71. /**
  72. * @var integer
  73. * @access private
  74. */
  75. var $_port;
  76. /**
  77. * @var string
  78. * @access private
  79. */
  80. var $_nick;
  81. /**
  82. * @var string
  83. * @access private
  84. */
  85. var $_username;
  86. /**
  87. * @var string
  88. * @access private
  89. */
  90. var $_realname;
  91. /**
  92. * @var string
  93. * @access private
  94. */
  95. var $_usermode;
  96. /**
  97. * @var string
  98. * @access private
  99. */
  100. var $_password;
  101. /**
  102. * @var boolean
  103. * @access private
  104. */
  105. var $_state = false;
  106. /**
  107. * @var array
  108. * @access private
  109. */
  110. var $_actionhandler = array();
  111. /**
  112. * @var array
  113. * @access private
  114. */
  115. var $_timehandler = array();
  116. /**
  117. * @var integer
  118. * @access private
  119. */
  120. var $_debug = SMARTIRC_DEBUG_NOTICE;
  121. /**
  122. * @var array
  123. * @access private
  124. */
  125. var $_messagebuffer = array();
  126. /**
  127. * @var integer
  128. * @access private
  129. */
  130. var $_messagebuffersize;
  131. /**
  132. * @var boolean
  133. * @access private
  134. */
  135. var $_usesockets = false;
  136. /**
  137. * @var integer
  138. * @access private
  139. */
  140. var $_receivedelay = 100;
  141. /**
  142. * @var integer
  143. * @access private
  144. */
  145. var $_senddelay = 250;
  146. /**
  147. * @var integer
  148. * @access private
  149. */
  150. var $_logdestination = SMARTIRC_STDOUT;
  151. /**
  152. * @var resource
  153. * @access private
  154. */
  155. var $_logfilefp = 0;
  156. /**
  157. * @var string
  158. * @access private
  159. */
  160. var $_logfile = 'Net_SmartIRC.log';
  161. /**
  162. * @var integer
  163. * @access private
  164. */
  165. var $_disconnecttime = 1000;
  166. /**
  167. * @var boolean
  168. * @access private
  169. */
  170. var $_loggedin = false;
  171. /**
  172. * @var boolean
  173. * @access private
  174. */
  175. var $_benchmark = false;
  176. /**
  177. * @var integer
  178. * @access private
  179. */
  180. var $_benchmark_starttime;
  181. /**
  182. * @var integer
  183. * @access private
  184. */
  185. var $_benchmark_stoptime;
  186. /**
  187. * @var integer
  188. * @access private
  189. */
  190. var $_actionhandlerid = 0;
  191. /**
  192. * @var integer
  193. * @access private
  194. */
  195. var $_timehandlerid = 0;
  196. /**
  197. * @var array
  198. * @access private
  199. */
  200. var $_motd = array();
  201. /**
  202. * @var array
  203. * @access private
  204. */
  205. var $_channels = array();
  206. /**
  207. * @var boolean
  208. * @access private
  209. */
  210. var $_channelsyncing = false;
  211. /**
  212. * @var string
  213. * @access private
  214. */
  215. var $_ctcpversion;
  216. /**
  217. * @var mixed
  218. * @access private
  219. */
  220. var $_mintimer = false;
  221. /**
  222. * @var integer
  223. * @access private
  224. */
  225. var $_maxtimer = 300000;
  226. /**
  227. * @var integer
  228. * @access private
  229. */
  230. var $_txtimeout = 300;
  231. /**
  232. * @var integer
  233. * @access private
  234. */
  235. var $_rxtimeout = 300;
  236. /**
  237. * @var integer
  238. * @access private
  239. */
  240. var $_selecttimeout;
  241. /**
  242. * @var integer
  243. * @access private
  244. */
  245. var $_lastrx;
  246. /**
  247. * @var integer
  248. * @access private
  249. */
  250. var $_lasttx;
  251. /**
  252. * @var boolean
  253. * @access private
  254. */
  255. var $_autoreconnect = false;
  256. /**
  257. * @var boolean
  258. * @access private
  259. */
  260. var $_autoretry = false;
  261. /**
  262. * All IRC replycodes, the index is the replycode name.
  263. *
  264. * @see $SMARTIRC_replycodes
  265. * @var array
  266. * @access public
  267. */
  268. var $replycodes;
  269. /**
  270. * All numeric IRC replycodes, the index is the numeric replycode.
  271. *
  272. * @see $SMARTIRC_nreplycodes
  273. * @var array
  274. * @access public
  275. */
  276. var $nreplycodes;
  277. /**
  278. * Stores all channels in this array where we are joined, works only if channelsyncing is activated.
  279. * Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
  280. * $irc->channel['#test']->users['meebey']->nick;
  281. *
  282. * @see setChannelSyncing()
  283. * @see Net_SmartIRC_channel
  284. * @see Net_SmartIRC_channeluser
  285. * @var array
  286. * @access public
  287. */
  288. var $channel;
  289. /**
  290. * Constructor. Initiales the messagebuffer and "links" the replycodes from
  291. * global into properties. Also some PHP runtime settings are configured.
  292. *
  293. * @access public
  294. * @return void
  295. */
  296. function Net_SmartIRC_base()
  297. {
  298. // precheck
  299. $this->_checkPHPVersion();
  300. ob_implicit_flush(true);
  301. @set_time_limit(0);
  302. ignore_user_abort(true);
  303. $this->_messagebuffer[SMARTIRC_CRITICAL] = array();
  304. $this->_messagebuffer[SMARTIRC_HIGH] = array();
  305. $this->_messagebuffer[SMARTIRC_MEDIUM] = array();
  306. $this->_messagebuffer[SMARTIRC_LOW] = array();
  307. $this->replycodes = &$GLOBALS['SMARTIRC_replycodes'];
  308. $this->nreplycodes = &$GLOBALS['SMARTIRC_nreplycodes'];
  309. // hack till PHP allows (PHP5) $object->method($param)->$object
  310. $this->channel = &$this->_channels;
  311. // another hack
  312. $this->user = &$this->_users;
  313. if (isset($_SERVER['REQUEST_METHOD'])) {
  314. // the script is called from a browser, lets set default log destination
  315. // to SMARTIRC_BROWSEROUT (makes browser friendly output)
  316. $this->setLogdestination(SMARTIRC_BROWSEROUT);
  317. }
  318. }
  319. /**
  320. * Enables/disables the usage of real sockets.
  321. *
  322. * Enables/disables the usage of real sockets instead of fsocks
  323. * (works only if your PHP build has loaded the PHP socket extension)
  324. * Default: false
  325. *
  326. * @param bool $boolean
  327. * @return void
  328. * @access public
  329. */
  330. function setUseSockets($boolean)
  331. {
  332. if ($boolean === true) {
  333. if (@extension_loaded('sockets')) {
  334. $this->_usesockets = true;
  335. } else {
  336. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket extension not loaded, trying to load it...', __FILE__, __LINE__);
  337. if (strtoupper(substr(PHP_OS, 0,3) == 'WIN')) {
  338. $load_status = @dl('php_sockets.dll');
  339. } else {
  340. $load_status = @dl('sockets.so');
  341. }
  342. if ($load_status) {
  343. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket extension succesfully loaded', __FILE__, __LINE__);
  344. $this->_usesockets = true;
  345. } else {
  346. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: couldn\'t load the socket extension', __FILE__, __LINE__);
  347. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: your PHP build doesn\'t support real sockets, will use fsocks instead', __FILE__, __LINE__);
  348. $this->_usesockets = false;
  349. }
  350. }
  351. } else {
  352. $this->_usesockets = false;
  353. }
  354. }
  355. /**
  356. * Sets the level of debug messages.
  357. *
  358. * Sets the debug level (bitwise), useful for testing/developing your code.
  359. * Here the list of all possible debug levels:
  360. * SMARTIRC_DEBUG_NONE
  361. * SMARTIRC_DEBUG_NOTICE
  362. * SMARTIRC_DEBUG_CONNECTION
  363. * SMARTIRC_DEBUG_SOCKET
  364. * SMARTIRC_DEBUG_IRCMESSAGES
  365. * SMARTIRC_DEBUG_MESSAGETYPES
  366. * SMARTIRC_DEBUG_ACTIONHANDLER
  367. * SMARTIRC_DEBUG_TIMEHANDLER
  368. * SMARTIRC_DEBUG_MESSAGEHANDLER
  369. * SMARTIRC_DEBUG_CHANNELSYNCING
  370. * SMARTIRC_DEBUG_MODULES
  371. * SMARTIRC_DEBUG_USERSYNCING
  372. * SMARTIRC_DEBUG_ALL
  373. *
  374. * Default: SMARTIRC_DEBUG_NOTICE
  375. *
  376. * @see DOCUMENTATION
  377. * @see SMARTIRC_DEBUG_NOTICE
  378. * @param integer $level
  379. * @return void
  380. * @access public
  381. */
  382. function setDebug($level)
  383. {
  384. $this->_debug = $level;
  385. }
  386. /**
  387. * Enables/disables the benchmark engine.
  388. *
  389. * @param boolean $boolean
  390. * @return void
  391. * @access public
  392. */
  393. function setBenchmark($boolean)
  394. {
  395. if (is_bool($boolean)) {
  396. $this->_benchmark = $boolean;
  397. } else {
  398. $this->_benchmark = false;
  399. }
  400. }
  401. /**
  402. * Deprecated, use setChannelSyncing() instead!
  403. *
  404. * @deprecated
  405. * @param boolean $boolean
  406. * @return void
  407. * @access public
  408. */
  409. function setChannelSynching($boolean)
  410. {
  411. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: you are using setChannelSynching() which is a deprecated method, use setChannelSyncing() instead!', __FILE__, __LINE__);
  412. $this->setChannelSyncing($boolean);
  413. }
  414. /**
  415. * Enables/disables channel syncing.
  416. *
  417. * Channel syncing means, all users on all channel we are joined are tracked in the
  418. * channel array. This makes it very handy for botcoding.
  419. *
  420. * @param boolean $boolean
  421. * @return void
  422. * @access public
  423. */
  424. function setChannelSyncing($boolean)
  425. {
  426. if (is_bool($boolean)) {
  427. $this->_channelsyncing = $boolean;
  428. } else {
  429. $this->_channelsyncing = false;
  430. }
  431. if ($this->_channelsyncing == true) {
  432. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: Channel syncing enabled', __FILE__, __LINE__);
  433. } else {
  434. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: Channel syncing disabled', __FILE__, __LINE__);
  435. }
  436. }
  437. /**
  438. * Sets the CTCP version reply string.
  439. *
  440. * @param string $versionstring
  441. * @return void
  442. * @access public
  443. */
  444. function setCtcpVersion($versionstring)
  445. {
  446. $this->_ctcpversion = $versionstring;
  447. }
  448. /**
  449. * Sets the destination of all log messages.
  450. *
  451. * Sets the destination of log messages.
  452. * $type can be:
  453. * SMARTIRC_FILE for saving the log into a file
  454. * SMARTIRC_STDOUT for echoing the log to stdout
  455. * SMARTIRC_SYSLOG for sending the log to the syslog
  456. * Default: SMARTIRC_STDOUT
  457. *
  458. * @see SMARTIRC_STDOUT
  459. * @param integer $type must be on of the constants
  460. * @return void
  461. * @access public
  462. */
  463. function setLogdestination($type)
  464. {
  465. switch ($type) {
  466. case (SMARTIRC_FILE ||
  467. SMARTIRC_STDOUT ||
  468. SMARTIRC_SYSLOG ||
  469. SMARTIRC_BROWSEROUT ||
  470. SMARTIRC_NONE):
  471. $this->_logdestination = $type;
  472. break;
  473. default:
  474. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: unknown logdestination type ('.$type.'), will use STDOUT instead', __FILE__, __LINE__);
  475. $this->_logdestination = SMARTIRC_STDOUT;
  476. }
  477. }
  478. /**
  479. * Sets the file for the log if the destination is set to file.
  480. *
  481. * Sets the logfile, if {@link setLogdestination logdestination} is set to SMARTIRC_FILE.
  482. * This should be only used with full path!
  483. *
  484. * @param string $file
  485. * @return void
  486. * @access public
  487. */
  488. function setLogfile($file)
  489. {
  490. $this->_logfile = $file;
  491. }
  492. /**
  493. * Sets the delaytime before closing the socket when disconnect.
  494. *
  495. * @param integer $milliseconds
  496. * @return void
  497. * @access public
  498. */
  499. function setDisconnecttime($milliseconds)
  500. {
  501. if (is_integer($milliseconds) && $milliseconds >= 100) {
  502. $this->_disconnecttime = $milliseconds;
  503. } else {
  504. $this->_disconnecttime = 100;
  505. }
  506. }
  507. /**
  508. * Sets the delay for receiving data from the IRC server.
  509. *
  510. * Sets the delaytime between messages that are received, this reduces your CPU load.
  511. * Don't set this too low (min 100ms).
  512. * Default: 100
  513. *
  514. * @param integer $milliseconds
  515. * @return void
  516. * @access public
  517. */
  518. function setReceivedelay($milliseconds)
  519. {
  520. if (is_integer($milliseconds) && $milliseconds >= 100) {
  521. $this->_receivedelay = $milliseconds;
  522. } else {
  523. $this->_receivedelay = 100;
  524. }
  525. }
  526. /**
  527. * Sets the delay for sending data to the IRC server.
  528. *
  529. * Sets the delaytime between messages that are sent, because IRC servers doesn't like floods.
  530. * This will avoid sending your messages too fast to the IRC server.
  531. * Default: 250
  532. *
  533. * @param integer $milliseconds
  534. * @return void
  535. * @access public
  536. */
  537. function setSenddelay($milliseconds)
  538. {
  539. if (is_integer($milliseconds)) {
  540. $this->_senddelay = $milliseconds;
  541. } else {
  542. $this->_senddelay = 250;
  543. }
  544. }
  545. /**
  546. * Enables/disables autoreconnecting.
  547. *
  548. * @param boolean $boolean
  549. * @return void
  550. * @access public
  551. */
  552. function setAutoReconnect($boolean)
  553. {
  554. if (is_bool($boolean)) {
  555. $this->_autoreconnect = $boolean;
  556. } else {
  557. $this->_autoreconnect = false;
  558. }
  559. }
  560. /**
  561. * Enables/disables autoretry for connecting to a server.
  562. *
  563. * @param boolean $boolean
  564. * @return void
  565. * @access public
  566. */
  567. function setAutoRetry($boolean)
  568. {
  569. if (is_bool($boolean)) {
  570. $this->_autoretry = $boolean;
  571. } else {
  572. $this->_autoretry = false;
  573. }
  574. }
  575. /**
  576. * Sets the receive timeout.
  577. *
  578. * If the timeout occurs, the connection will be reinitialized
  579. * Default: 300 seconds
  580. *
  581. * @param integer $seconds
  582. * @return void
  583. * @access public
  584. */
  585. function setReceiveTimeout($seconds)
  586. {
  587. if (is_integer($seconds)) {
  588. $this->_rxtimeout = $seconds;
  589. } else {
  590. $this->_rxtimeout = 300;
  591. }
  592. }
  593. /**
  594. * Sets the transmit timeout.
  595. *
  596. * If the timeout occurs, the connection will be reinitialized
  597. * Default: 300 seconds
  598. *
  599. * @param integer $seconds
  600. * @return void
  601. * @access public
  602. */
  603. function setTransmitTimeout($seconds)
  604. {
  605. if (is_integer($seconds)) {
  606. $this->_txtimeout = $seconds;
  607. } else {
  608. $this->_txtimeout = 300;
  609. }
  610. }
  611. /**
  612. * Starts the benchmark (sets the counters).
  613. *
  614. * @return void
  615. * @access public
  616. */
  617. function startBenchmark()
  618. {
  619. $this->_benchmark_starttime = $this->_microint();
  620. $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark started', __FILE__, __LINE__);
  621. }
  622. /**
  623. * Stops the benchmark and displays the result.
  624. *
  625. * @return void
  626. * @access public
  627. */
  628. function stopBenchmark()
  629. {
  630. $this->_benchmark_stoptime = $this->_microint();
  631. $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark stopped', __FILE__, __LINE__);
  632. if ($this->_benchmark) {
  633. $this->showBenchmark();
  634. }
  635. }
  636. /**
  637. * Shows the benchmark result.
  638. *
  639. * @return void
  640. * @access public
  641. */
  642. function showBenchmark()
  643. {
  644. $this->log(SMARTIRC_DEBUG_NOTICE, 'benchmark time: '.((float)$this->_benchmark_stoptime-(float)$this->_benchmark_starttime), __FILE__, __LINE__);
  645. }
  646. /**
  647. * Adds an entry to the log.
  648. *
  649. * Adds an entry to the log with Linux style log format.
  650. * Possible $level constants (can also be combined with "|"s)
  651. * SMARTIRC_DEBUG_NONE
  652. * SMARTIRC_DEBUG_NOTICE
  653. * SMARTIRC_DEBUG_CONNECTION
  654. * SMARTIRC_DEBUG_SOCKET
  655. * SMARTIRC_DEBUG_IRCMESSAGES
  656. * SMARTIRC_DEBUG_MESSAGETYPES
  657. * SMARTIRC_DEBUG_ACTIONHANDLER
  658. * SMARTIRC_DEBUG_TIMEHANDLER
  659. * SMARTIRC_DEBUG_MESSAGEHANDLER
  660. * SMARTIRC_DEBUG_CHANNELSYNCING
  661. * SMARTIRC_DEBUG_MODULES
  662. * SMARTIRC_DEBUG_USERSYNCING
  663. * SMARTIRC_DEBUG_ALL
  664. *
  665. * @see SMARTIRC_DEBUG_NOTICE
  666. * @param integer $level bit constants (SMARTIRC_DEBUG_*)
  667. * @param string $entry the new log entry
  668. * @return void
  669. * @access public
  670. */
  671. function log($level, $entry, $file = null, $line = null)
  672. {
  673. // prechecks
  674. if (!(is_integer($level)) ||
  675. !($level & SMARTIRC_DEBUG_ALL)) {
  676. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: invalid log level passed to log() ('.$level.')', __FILE__, __LINE__);
  677. return;
  678. }
  679. if (!($level & $this->_debug) ||
  680. ($this->_logdestination == SMARTIRC_NONE)) {
  681. return;
  682. }
  683. if (substr($entry, -1) != "\n") {
  684. $entry .= "\n";
  685. }
  686. if ($file !== null &&
  687. $line !== null) {
  688. $file = basename($file);
  689. $entry = $file.'('.$line.') '.$entry;
  690. } else {
  691. $entry = 'unknown(0) '.$entry;
  692. }
  693. $formatedentry = date('M d H:i:s ').$entry;
  694. switch ($this->_logdestination) {
  695. case SMARTIRC_STDOUT:
  696. echo $formatedentry;
  697. flush();
  698. break;
  699. case SMARTIRC_BROWSEROUT:
  700. echo '<pre>'.htmlentities($formatedentry).'</pre>';
  701. break;
  702. case SMARTIRC_FILE:
  703. if (!is_resource($this->_logfilefp)) {
  704. if ($this->_logfilefp === null) {
  705. // we reconncted and don't want to destroy the old log entries
  706. $this->_logfilefp = @fopen($this->_logfile,'a');
  707. } else {
  708. $this->_logfilefp = @fopen($this->_logfile,'w');
  709. }
  710. }
  711. @fwrite($this->_logfilefp, $formatedentry);
  712. fflush($this->_logfilefp);
  713. break;
  714. case SMARTIRC_SYSLOG:
  715. define_syslog_variables();
  716. if (!is_int($this->_logfilefp)) {
  717. $this->_logfilefp = openlog('Net_SmartIRC', LOG_NDELAY, LOG_DAEMON);
  718. }
  719. syslog(LOG_INFO, $entry);
  720. break;
  721. }
  722. }
  723. /**
  724. * Returns the full motd.
  725. *
  726. * @return array
  727. * @access public
  728. */
  729. function getMotd()
  730. {
  731. return $this->_motd;
  732. }
  733. /**
  734. * Returns the usermode.
  735. *
  736. * @return string
  737. * @access public
  738. */
  739. function getUsermode()
  740. {
  741. return $this->_usermode;
  742. }
  743. /**
  744. * Creates the sockets and connects to the IRC server on the given port.
  745. *
  746. * @param string $address
  747. * @param integer $port
  748. * @return void
  749. * @access public
  750. */
  751. function connect($address, $port)
  752. {
  753. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connecting', __FILE__, __LINE__);
  754. $this->_address = $address;
  755. $this->_port = $port;
  756. if ($this->_usesockets == true) {
  757. $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: using real sockets', __FILE__, __LINE__);
  758. $this->_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  759. $result = @socket_connect($this->_socket, $this->_address, $this->_port);
  760. } else {
  761. $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: using fsockets', __FILE__, __LINE__);
  762. $result = @fsockopen($this->_address, $this->_port, $errno, $errstr);
  763. }
  764. if ($result === false) {
  765. if ($this->_usesockets == true) {
  766. $error = socket_strerror(socket_last_error($this->_socket));
  767. } else {
  768. $error = $errstr.' ('.$errno.')';
  769. }
  770. $error_msg = 'couldn\'t connect to "'.$address.'" reason: "'.$error.'"';
  771. $this->log(SMARTIRC_DEBUG_NOTICE, 'DEBUG_NOTICE: '.$error_msg, __FILE__, __LINE__);
  772. // TODO! muss return wert sein
  773. $this->throwError($error_msg);
  774. // doesn't work somehow.... I only want to retry 4 times! no endless loop (causes segfault)
  775. static $tries = 0;
  776. if ($this->_autoretry == true && $tries < 5) {
  777. $this->reconnect();
  778. $tries++;
  779. } else {
  780. die();
  781. }
  782. } else {
  783. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connected', __FILE__, __LINE__);
  784. if ($this->_usesockets != true) {
  785. $this->_socket = $result;
  786. $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: activating nonblocking fsocket mode', __FILE__, __LINE__);
  787. socket_set_blocking($this->_socket, false);
  788. }
  789. }
  790. $this->_lastrx = time();
  791. $this->_lasttx = $this->_lastrx;
  792. $this->_updatestate();
  793. if ($result !== false) {
  794. return true;
  795. } else {
  796. return false;
  797. }
  798. }
  799. /**
  800. * Disconnects from the IRC server nicely with a QUIT or just destroys the socket.
  801. *
  802. * Disconnects from the IRC server in the given quickness mode.
  803. * $quickdisconnect:
  804. * true, just close the socket
  805. * false, send QUIT and wait {@link $_disconnectime $_disconnectime} before closing the socket
  806. *
  807. * @param boolean $quickdisconnect default: false
  808. * @return boolean
  809. * @access public
  810. */
  811. function disconnect($quickdisconnect = false)
  812. {
  813. if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
  814. if ($quickdisconnect == false) {
  815. $this->_send('QUIT', SMARTIRC_CRITICAL);
  816. usleep($this->_disconnecttime*1000);
  817. }
  818. if ($this->_usesockets == true) {
  819. @socket_shutdown($this->_socket);
  820. @socket_close($this->_socket);
  821. } else {
  822. fclose($this->_socket);
  823. }
  824. $this->_updatestate();
  825. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: disconnected', __FILE__, __LINE__);
  826. } else {
  827. return false;
  828. }
  829. if ($this->_channelsyncing == true) {
  830. // let's clean our channel array
  831. $this->_channels = array();
  832. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: cleaned channel array', __FILE__, __LINE__);
  833. }
  834. if ($this->_logdestination == SMARTIRC_FILE) {
  835. fclose($this->_logfilefp);
  836. $this->_logfilefp = null;
  837. } else if ($this->_logdestination == SMARTIRC_SYSLOG) {
  838. closelog();
  839. }
  840. return true;
  841. }
  842. /**
  843. * Reconnects to the IRC server with the same login info,
  844. * it also rejoins the channels
  845. *
  846. * @return void
  847. * @access public
  848. */
  849. function reconnect()
  850. {
  851. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: reconnecting...', __FILE__, __LINE__);
  852. // remember in which channels we are joined
  853. $channels = array();
  854. foreach ($this->_channels as $value) {
  855. if (empty($value->key)) {
  856. $channels[] = array('name' => $value->name);
  857. } else {
  858. $channels[] = array('name' => $value->name, 'key' => $value->key);
  859. }
  860. }
  861. $this->disconnect(true);
  862. $this->connect($this->_address, $this->_port);
  863. $this->login($this->_nick, $this->_realname, $this->_usermode, $this->_username, $this->_password);
  864. // rejoin the channels
  865. foreach ($channels as $value) {
  866. if (isset($value['key'])) {
  867. $this->join($value['name'], $value['key']);
  868. } else {
  869. $this->join($value['name']);
  870. }
  871. }
  872. }
  873. /**
  874. * login and register nickname on the IRC network
  875. *
  876. * Registers the nickname and user information on the IRC network.
  877. *
  878. * @param string $nick
  879. * @param string $realname
  880. * @param integer $usermode
  881. * @param string $username
  882. * @param string $password
  883. * @return void
  884. * @access public
  885. */
  886. function login($nick, $realname, $usermode = 0, $username = null, $password = null)
  887. {
  888. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: logging in', __FILE__, __LINE__);
  889. $this->_nick = str_replace(' ', '', $nick);
  890. $this->_realname = $realname;
  891. if ($username !== null) {
  892. $this->_username = str_replace(' ', '', $username);
  893. } else {
  894. $this->_username = str_replace(' ', '', exec('whoami'));
  895. }
  896. if ($password !== null) {
  897. $this->_password = $password;
  898. $this->_send('PASS '.$this->_password, SMARTIRC_CRITICAL);
  899. }
  900. if (!is_numeric($usermode)) {
  901. $this->log(SMARTIRC_DEBUG_NOTICE, 'DEBUG_NOTICE: login() usermode ('.$usermode.') is not valid, will use 0 instead', __FILE__, __LINE__);
  902. $usermode = 0;
  903. }
  904. $this->_send('NICK '.$this->_nick, SMARTIRC_CRITICAL);
  905. $this->_send('USER '.$this->_username.' '.$usermode.' '.SMARTIRC_UNUSED.' :'.$this->_realname, SMARTIRC_CRITICAL);
  906. }
  907. // </IRC methods>
  908. /**
  909. * checks if we or the given user is joined to the specified channel and returns the result
  910. * ChannelSyncing is required for this.
  911. *
  912. * @see setChannelSyncing
  913. * @param string $channel
  914. * @param string $nickname
  915. * @return boolean
  916. * @access public
  917. */
  918. function isJoined($channel, $nickname = null)
  919. {
  920. if ($this->_channelsyncing != true) {
  921. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isJoined() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
  922. return false;
  923. }
  924. if ($nickname === null) {
  925. $nickname = $this->_nick;
  926. }
  927. if (isset($this->_channels[strtolower($channel)]->users[strtolower($nickname)])) {
  928. return true;
  929. }
  930. return false;
  931. }
  932. /**
  933. * Checks if we or the given user is opped on the specified channel and returns the result.
  934. * ChannelSyncing is required for this.
  935. *
  936. * @see setChannelSyncing
  937. * @param string $channel
  938. * @param string $nickname
  939. * @return boolean
  940. * @access public
  941. */
  942. function isOpped($channel, $nickname = null)
  943. {
  944. if ($this->_channelsyncing != true) {
  945. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isOpped() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
  946. return false;
  947. }
  948. if ($nickname === null) {
  949. $nickname = $this->_nick;
  950. }
  951. if ($this->isJoined($channel, $nickname)) {
  952. if ($this->_channels[strtolower($channel)]->users[strtolower($nickname)]->op) {
  953. return true;
  954. }
  955. }
  956. return false;
  957. }
  958. /**
  959. * Checks if we or the given user is voiced on the specified channel and returns the result.
  960. * ChannelSyncing is required for this.
  961. *
  962. * @see setChannelSyncing
  963. * @param string $channel
  964. * @param string $nickname
  965. * @return boolean
  966. * @access public
  967. */
  968. function isVoiced($channel, $nickname = null)
  969. {
  970. if ($this->_channelsyncing != true) {
  971. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isVoiced() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
  972. return false;
  973. }
  974. if ($nickname === null) {
  975. $nickname = $this->_nick;
  976. }
  977. if ($this->isJoined($channel, $nickname)) {
  978. if ($this->_channels[strtolower($channel)]->users[strtolower($nickname)]->voice) {
  979. return true;
  980. }
  981. }
  982. return false;
  983. }
  984. /**
  985. * Checks if the hostmask is on the specified channel banned and returns the result.
  986. * ChannelSyncing is required for this.
  987. *
  988. * @see setChannelSyncing
  989. * @param string $channel
  990. * @param string $hostmask
  991. * @return boolean
  992. * @access public
  993. */
  994. function isBanned($channel, $hostmask)
  995. {
  996. if ($this->_channelsyncing != true) {
  997. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: isBanned() is called and the required Channel Syncing is not activated!', __FILE__, __LINE__);
  998. return false;
  999. }
  1000. if ($this->isJoined($channel)) {
  1001. $result = array_search($hostmask, $this->_channels[strtolower($channel)]->bans);
  1002. if ($result !== false) {
  1003. return true;
  1004. }
  1005. }
  1006. return false;
  1007. }
  1008. /**
  1009. * goes into receive mode
  1010. *
  1011. * Goes into receive and idle mode. Only call this if you want to "spawn" the bot.
  1012. * No further lines of PHP code will be processed after this call, only the bot methods!
  1013. *
  1014. * @return boolean
  1015. * @access public
  1016. */
  1017. function listen()
  1018. {
  1019. if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
  1020. $this->_rawreceive();
  1021. return true;
  1022. } else {
  1023. return false;
  1024. }
  1025. }
  1026. /**
  1027. * waits for a special message type and puts the answer in $result
  1028. *
  1029. * Creates a special actionhandler for that given TYPE and returns the answer.
  1030. * This will only receive the requested type, immediately quit and disconnect from the IRC server.
  1031. * Made for showing IRC statistics on your homepage, or other IRC related information.
  1032. *
  1033. * @param integer $messagetype see in the documentation 'Message Types'
  1034. * @return array answer from the IRC server for this $messagetype
  1035. * @access public
  1036. */
  1037. function listenFor($messagetype)
  1038. {
  1039. $listenfor = &new Net_SmartIRC_listenfor();
  1040. $this->registerActionhandler($messagetype, '.*', $listenfor, 'handler');
  1041. $this->listen();
  1042. $result = $listenfor->result;
  1043. if (isset($listenfor)) {
  1044. unset($listenfor);
  1045. }
  1046. return $result;
  1047. }
  1048. /**
  1049. * waits for a special message type and puts the answer in $result
  1050. *
  1051. * Creates a special actionhandler for that given TYPE and returns the answer.
  1052. * This will only receive the requested type, immediately quit and disconnect from the IRC server.
  1053. * Made for showing IRC statistics on your homepage, or other IRC related information.
  1054. * This special version of listenFor() stores the whole ircdata object, not just the message!
  1055. *
  1056. * @param integer $messagetype see in the documentation 'Message Types'
  1057. * @return array answer from the IRC server for this $messagetype
  1058. * @access public
  1059. */
  1060. function objListenFor($messagetype)
  1061. {
  1062. $objlistenfor = &new Net_SmartIRC_objListenFor();
  1063. $this->registerActionhandler($messagetype, '.*', $objlistenfor, 'handler');
  1064. $this->listen();
  1065. $result = $objlistenfor->result;
  1066. if (isset($objlistenfor)) {
  1067. unset($objlistenfor);
  1068. }
  1069. return $result;
  1070. }
  1071. /**
  1072. * registers a new actionhandler and returns the assigned id
  1073. *
  1074. * Registers an actionhandler in Net_SmartIRC for calling it later.
  1075. * The actionhandler id is needed for unregistering the actionhandler.
  1076. *
  1077. * @see example.php
  1078. * @param integer $handlertype bits constants, see in this documentation Message Types
  1079. * @param string $regexhandler the message that has to be in the IRC message in regex syntax
  1080. * @param object $object a reference to the objects of the method
  1081. * @param string $methodname the methodname that will be called when the handler happens
  1082. * @return integer assigned actionhandler id
  1083. * @access public
  1084. */
  1085. function registerActionhandler($handlertype, $regexhandler, &$object, $methodname)
  1086. {
  1087. // precheck
  1088. if (!$this->_isValidType($handlertype)) {
  1089. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: passed invalid handlertype to registerActionhandler()', __FILE__, __LINE__);
  1090. return false;
  1091. }
  1092. $id = $this->_actionhandlerid++;
  1093. $newactionhandler = &new Net_SmartIRC_actionhandler();
  1094. $newactionhandler->id = $id;
  1095. $newactionhandler->type = $handlertype;
  1096. $newactionhandler->message = $regexhandler;
  1097. $newactionhandler->object = &$object;
  1098. $newactionhandler->method = $methodname;
  1099. $this->_actionhandler[] = &$newactionhandler;
  1100. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') registered', __FILE__, __LINE__);
  1101. return $id;
  1102. }
  1103. /**
  1104. * unregisters an existing actionhandler
  1105. *
  1106. * @param integer $handlertype
  1107. * @param string $regexhandler
  1108. * @param object $object
  1109. * @param string $methodname
  1110. * @return boolean
  1111. * @access public
  1112. */
  1113. function unregisterActionhandler($handlertype, $regexhandler, &$object, $methodname)
  1114. {
  1115. // precheck
  1116. if (!$this->_isValidType($handlertype)) {
  1117. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: passed invalid handlertype to unregisterActionhandler()', __FILE__, __LINE__);
  1118. return false;
  1119. }
  1120. $handler = &$this->_actionhandler;
  1121. $handlercount = count($handler);
  1122. for ($i = 0; $i < $handlercount; $i++) {
  1123. $handlerobject = &$handler[$i];
  1124. if ($handlerobject->type == $handlertype &&
  1125. $handlerobject->message == $regexhandler &&
  1126. $handlerobject->method == $methodname) {
  1127. $id = $handlerobject->id;
  1128. if (isset($this->_actionhandler[$i])) {
  1129. unset($this->_actionhandler[$i]);
  1130. }
  1131. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') unregistered', __FILE__, __LINE__);
  1132. $this->_reorderactionhandler();
  1133. return true;
  1134. }
  1135. }
  1136. $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__);
  1137. return false;
  1138. }
  1139. /**
  1140. * unregisters an existing actionhandler via the id
  1141. *
  1142. * @param integer $id
  1143. * @return boolean
  1144. * @access public
  1145. */
  1146. function unregisterActionid($id)
  1147. {
  1148. $handler = &$this->_actionhandler;
  1149. $handlercount = count($handler);
  1150. for ($i = 0; $i < $handlercount; $i++) {
  1151. $handlerobject = &$handler[$i];
  1152. if ($handlerobject->id == $id) {
  1153. if (isset($this->_actionhandler[$i])) {
  1154. unset($this->_actionhandler[$i]);
  1155. }
  1156. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler('.$id.') unregistered', __FILE__, __LINE__);
  1157. $this->_reorderactionhandler();
  1158. return true;
  1159. }
  1160. }
  1161. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: could not find actionhandler id: '.$id.' _not_ unregistered', __FILE__, __LINE__);
  1162. return false;
  1163. }
  1164. /**
  1165. * registers a timehandler and returns the assigned id
  1166. *
  1167. * Registers a timehandler in Net_SmartIRC, which will be called in the specified interval.
  1168. * The timehandler id is needed for unregistering the timehandler.
  1169. *
  1170. * @see example7.php
  1171. * @param integer $interval interval time in milliseconds
  1172. * @param object $object a reference to the objects of the method
  1173. * @param string $methodname the methodname that will be called when the handler happens
  1174. * @return integer assigned timehandler id
  1175. * @access public
  1176. */
  1177. function registerTimehandler($interval, &$object, $methodname)
  1178. {
  1179. $id = $this->_timehandlerid++;
  1180. $newtimehandler = &new Net_SmartIRC_timehandler();
  1181. $newtimehandler->id = $id;
  1182. $newtimehandler->interval = $interval;
  1183. $newtimehandler->object = &$object;
  1184. $newtimehandler->method = $methodname;
  1185. $newtimehandler->lastmicrotimestamp = $this->_microint();
  1186. $this->_timehandler[] = &$newtimehandler;
  1187. $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: timehandler('.$id.') registered', __FILE__, __LINE__);
  1188. if (($interval < $this->_mintimer) || ($this->_mintimer == false)) {
  1189. $this->_mintimer = $interval;
  1190. }
  1191. return $id;
  1192. }
  1193. /**
  1194. * unregisters an existing timehandler via the id
  1195. *
  1196. * @see example7.php
  1197. * @param integer $id
  1198. * @return boolean
  1199. * @access public
  1200. */
  1201. function unregisterTimeid($id)
  1202. {
  1203. $handler = &$this->_timehandler;
  1204. $handlercount = count($handler);
  1205. for ($i = 0; $i < $handlercount; $i++) {
  1206. $handlerobject = &$handler[$i];
  1207. if ($handlerobject->id == $id) {
  1208. if (isset($this->_timehandler[$i])) {
  1209. unset($this->_timehandler[$i]);
  1210. }
  1211. $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: timehandler('.$id.') unregistered', __FILE__, __LINE__);
  1212. $this->_reordertimehandler();
  1213. $this->_updatemintimer();
  1214. return true;
  1215. }
  1216. }
  1217. $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: could not find timehandler id: '.$id.' _not_ unregistered', __FILE__, __LINE__);
  1218. return false;
  1219. }
  1220. // <private methods>
  1221. /**
  1222. * changes a already used nickname to a new nickname plus 3 random digits
  1223. *
  1224. * @return void
  1225. * @access private
  1226. */
  1227. function _nicknameinuse()
  1228. {
  1229. $newnickname = substr($this->_nick, 0, 5).rand(0, 999);
  1230. $this->changeNick($newnickname, SMARTIRC_CRITICAL);
  1231. }
  1232. /**
  1233. * sends an IRC message
  1234. *
  1235. * Adds a message to the messagequeue, with the optional priority.
  1236. * $priority:
  1237. * SMARTIRC_CRITICAL
  1238. * SMARTIRC_HIGH
  1239. * SMARTIRC_MEDIUM
  1240. * SMARTIRC_LOW
  1241. *
  1242. * @param string $data
  1243. * @param integer $priority must be one of the priority constants
  1244. * @return boolean
  1245. * @access private
  1246. */
  1247. function _send($data, $priority = SMARTIRC_MEDIUM)
  1248. {
  1249. switch ($priority) {
  1250. case SMARTIRC_CRITICAL:
  1251. $this->_rawsend($data);
  1252. return true;
  1253. break;
  1254. case (SMARTIRC_HIGH||
  1255. SMARTIRC_MEDIUM||
  1256. SMARTIRC_LOW):
  1257. $this->_messagebuffer[$priority][] = $data;
  1258. return true;
  1259. break;
  1260. default:
  1261. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: message ('.$data.') with an invalid priority passed ('.$priority.'), message is ignored!', __FILE__, __LINE__);
  1262. return false;
  1263. }
  1264. }
  1265. /**
  1266. * checks the buffer if there are messages to send
  1267. *
  1268. * @return void
  1269. * @access private
  1270. */
  1271. function _checkbuffer()
  1272. {
  1273. if (!$this->_loggedin) {
  1274. return;
  1275. }
  1276. static $highsent = 0;
  1277. static $lastmicrotimestamp = 0;
  1278. if ($lastmicrotimestamp == 0) {
  1279. $lastmicrotimestamp = $this->_microint();
  1280. }
  1281. $highcount = count($this->_messagebuffer[SMARTIRC_HIGH]);
  1282. $mediumcount = count($this->_messagebuffer[SMARTIRC_MEDIUM]);
  1283. $lowcount = count($this->_messagebuffer[SMARTIRC_LOW]);
  1284. $this->_messagebuffersize = $highcount+$mediumcount+$lowcount;
  1285. // don't send them too fast
  1286. if ($this->_microint() >= ($lastmicrotimestamp+($this->_senddelay/1000))) {
  1287. if ($highcount > 0 && $highsent <= 2) {
  1288. $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_HIGH]));
  1289. $lastmicrotimestamp = $this->_microint();
  1290. $highsent++;
  1291. } else if ($mediumcount > 0) {
  1292. $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_MEDIUM]));
  1293. $lastmicrotimestamp = $this->_microint();
  1294. $highsent = 0;
  1295. } else if ($lowcount > 0) {
  1296. $this->_rawsend(array_shift($this->_messagebuffer[SMARTIRC_LOW]));
  1297. $lastmicrotimestamp = $this->_microint();
  1298. }
  1299. }
  1300. }
  1301. /**
  1302. * Checks the running timers and calls the registered timehandler,
  1303. * when the interval is reached.
  1304. *
  1305. * @return void
  1306. * @access private
  1307. */
  1308. function _checktimer()
  1309. {
  1310. if (!$this->_loggedin) {
  1311. return;
  1312. }
  1313. // has to be count() because the array may change during the loop!
  1314. for ($i = 0; $i < count($this->_timehandler); $i++) {
  1315. $handlerobject = &$this->_timehandler[$i];
  1316. $microtimestamp = $this->_microint();
  1317. if ($microtimestamp >= ($handlerobject->lastmicrotimestamp+($handlerobject->interval/1000))) {
  1318. $methodobject = &$handlerobject->object;
  1319. $method = $handlerobject->method;
  1320. $handlerobject->lastmicrotimestamp = $microtimestamp;
  1321. if (@method_exists($methodobject, $method)) {
  1322. $this->log(SMARTIRC_DEBUG_TIMEHANDLER, 'DEBUG_TIMEHANDLER: calling method "'.get_class($methodobject).'->'.$method.'"', __FILE__, __LINE__);
  1323. $methodobject->$method($this);
  1324. }
  1325. }
  1326. }
  1327. }
  1328. /**
  1329. * Checks if a receive or transmit timeout occured and reconnects if configured
  1330. *
  1331. * @return void
  1332. * @access private
  1333. */
  1334. function _checktimeout()
  1335. {
  1336. if ($this->_autoreconnect == true) {
  1337. $timestamp = time();
  1338. if ($this->_lastrx < ($timestamp - $this->_rxtimeout)) {
  1339. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: receive timeout detected, doing reconnect...', __FILE__, __LINE__);
  1340. $this->reconnect();
  1341. } else if ($this->_lasttx < ($timestamp - $this->_txtimeout)) {
  1342. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: transmit timeout detected, doing reconnect...', __FILE__, __LINE__);
  1343. $this->reconnect();
  1344. }
  1345. }
  1346. }
  1347. /**
  1348. * sends a raw message to the IRC server (don't use this!!)
  1349. *
  1350. * Use message() or _send() instead.
  1351. *
  1352. * @param string $data
  1353. * @return boolean
  1354. * @access private
  1355. */
  1356. function _rawsend($data)
  1357. {
  1358. if ($this->_state() == SMARTIRC_STATE_CONNECTED) {
  1359. $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: sent: "'.$data.'"', __FILE__, __LINE__);
  1360. if ($this->_usesockets == true) {
  1361. $result = @socket_write($this->_socket, $data.SMARTIRC_CRLF);
  1362. } else {
  1363. $result = @fwrite($this->_socket, $data.SMARTIRC_CRLF);
  1364. }
  1365. if ($result === false) {
  1366. return false;
  1367. } else {
  1368. $this->_lasttx = time();
  1369. return true;
  1370. }
  1371. } else {
  1372. return false;
  1373. }
  1374. }
  1375. /**
  1376. * goes into main idle loop for waiting messages from the IRC server
  1377. *
  1378. * @return void
  1379. * @access private
  1380. */
  1381. function _rawreceive()
  1382. {
  1383. $lastpart = '';
  1384. $rawdataar = array();
  1385. while ($this->_state() == SMARTIRC_STATE_CONNECTED) {
  1386. $this->_checkbuffer();
  1387. $timeout = $this->_selecttimeout();
  1388. if ($this->_usesockets == true) {
  1389. $sread = array($this->_socket);
  1390. $result = @socket_select($sread, $w = null, $e = null, 0, $timeout*1000);
  1391. if ($result == 1) {
  1392. // the socket got data to read
  1393. $rawdata = @socket_read($this->_socket, 10240);
  1394. } else if ($result === false) {
  1395. // panic! panic! something went wrong!
  1396. $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: socket_select() returned false, something went wrong! Reason: '.socket_strerror(socket_last_error()), __FILE__, __LINE__);
  1397. exit;
  1398. } else {
  1399. // no data
  1400. $rawdata = null;
  1401. }
  1402. } else {
  1403. usleep($this->_receivedelay*1000);
  1404. $rawdata = @fread($this->_socket, 10240);
  1405. }
  1406. $this->_checktimer();
  1407. $this->_checktimeout();
  1408. if ($rawdata !== null && !empty($rawdata)) {
  1409. $this->_lastrx = time();
  1410. $rawdata = str_replace("\r", '', $rawdata);
  1411. $rawdata = $lastpart.$rawdata;
  1412. $lastpart = substr($rawdata, strrpos($rawdata ,"\n")+1);
  1413. $rawdata = substr($rawdata, 0, strrpos($rawdata ,"\n"));
  1414. $rawdataar = explode("\n", $rawdata);
  1415. }
  1416. // loop through our received messages
  1417. while (count($rawdataar) > 0) {
  1418. $rawline = array_shift($rawdataar);
  1419. $validmessage = false;
  1420. $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: received: "'.$rawline.'"', __FILE__, __LINE__);
  1421. // building our data packet
  1422. $ircdata = &new Net_SmartIRC_data();
  1423. $ircdata->rawmessage = $rawline;
  1424. $lineex = explode(' ', $rawline);
  1425. $ircdata->rawmessageex = $lineex;
  1426. $messagecode = $lineex[0];
  1427. if (substr($rawline, 0, 1) == ':') {
  1428. $validmessage = true;
  1429. $line = substr($rawline, 1);
  1430. $lineex = explode(' ', $line);
  1431. // conform to RFC 2812
  1432. $from = $lineex[0];
  1433. $messagecode = $lineex[1];
  1434. $exclamationpos = strpos($from, '!');
  1435. $atpos = strpos($from, '@');
  1436. $colonpos = strpos($line, ' :');
  1437. if ($colonpos !== false) {
  1438. // we want the exact position of ":" not beginning from the space
  1439. $colonpos += 1;
  1440. }
  1441. $ircdata->nick = substr($from, 0, $exclamationpos);
  1442. $ircdata->ident = substr($from, $exclamationpos+1, ($atpos-$exclamationpos)-1);
  1443. $ircdata->host = substr($from, $atpos+1);
  1444. $ircdata->type = $this->_gettype($rawline);
  1445. $ircdata->from = $from;
  1446. if ($colonpos !== false) {
  1447. $ircdata->message = substr($line, $colonpos+1);
  1448. $ircdata->messageex = explode(' ', $ircdata->message);
  1449. }
  1450. if ($ircdata->type & (SMARTIRC_TYPE_CHANNEL|
  1451. SMARTIRC_TYPE_ACTION|
  1452. SMARTIRC_TYPE_MODECHANGE|
  1453. SMARTIRC_TYPE_KICK|
  1454. SMARTIRC_TYPE_PART|
  1455. SMARTIRC_TYPE_JOIN)) {
  1456. $ircdata->channel = $lineex[2];
  1457. } else if ($ircdata->type & (SMARTIRC_TYPE_WHO|
  1458. SMARTIRC_TYPE_BANLIST|
  1459. SMARTIRC_TYPE_TOPIC|
  1460. SMARTIRC_TYPE_CHANNELMODE)) {
  1461. $ircdata->channel = $lineex[3];
  1462. } else if ($ircdata->type & SMARTIRC_TYPE_NAME) {
  1463. $ircdata->channel = $lineex[4];
  1464. }
  1465. if ($ircdata->channel !== null) {
  1466. if (substr($ircdata->channel, 0, 1) == ':') {
  1467. $ircdata->channel = substr($ircdata->channel, 1);
  1468. }
  1469. }
  1470. $this->log(SMARTIRC_DEBUG_MESSAGEPARSER, 'DEBUG_MESSAGEPARSER: ircdata nick: "'.$ircdata->nick.
  1471. '" ident: "'.$ircdata->ident.
  1472. '" host: "'.$ircdata->host.
  1473. '" type: "'.$ircdata->type.
  1474. '" from: "'.$ircdata->from.
  1475. '" channel: "'.$ircdata->channel.
  1476. '" message: "'.$ircdata->message.
  1477. '"', __FILE__, __LINE__);
  1478. }
  1479. // lets see if we have a messagehandler for it
  1480. $this->_handlemessage($messagecode, $ircdata);
  1481. if ($validmessage == true) {
  1482. // now the actionhandlers are comming
  1483. $this->_handleactionhandler($ircdata);
  1484. }
  1485. if (isset($ircdata)) {
  1486. unset($ircdata);
  1487. }
  1488. }
  1489. }
  1490. }
  1491. /**
  1492. * sends the pong for keeping alive
  1493. *
  1494. * Sends the PONG signal as reply of the PING from the IRC server.
  1495. *
  1496. * @param string $data
  1497. * @return void
  1498. * @access private
  1499. */
  1500. function _pong($data)
  1501. {
  1502. $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: Ping? Pong!', __FILE__, __LINE__);
  1503. $this->_send('PONG '.$data, SMARTIRC_CRITICAL);
  1504. }
  1505. /**
  1506. * returns the calculated selecttimeout value
  1507. *
  1508. * @return integer selecttimeout in microseconds
  1509. * @access private
  1510. */
  1511. function _selecttimeout() {
  1512. if ($this->_messagebuffersize == 0) {
  1513. $this->_selecttimeout = null;
  1514. if ($this->_mintimer != false) {
  1515. $this->_calculateselecttimeout($this->_mintimer);
  1516. }
  1517. if ($this->_autoreconnect == true) {
  1518. $this->_calculateselecttimeout($this->_rxtimeout*1000);
  1519. }
  1520. $this->_calculateselecttimeout($this->_maxtimer);
  1521. return $this->_selecttimeout;
  1522. } else {
  1523. return $this->_senddelay;
  1524. }
  1525. }
  1526. /**
  1527. * calculates the selecttimeout value
  1528. *
  1529. * @return void
  1530. * @access private
  1531. */
  1532. function _calculateselecttimeout($microseconds)
  1533. {
  1534. if (($this->_selecttimeout > $microseconds) || $this->_selecttimeout === null) {
  1535. $this->_selecttimeout = $microseconds;
  1536. }
  1537. }
  1538. /**
  1539. * updates _mintimer to the smallest timer interval
  1540. *
  1541. * @return void
  1542. * @access private
  1543. */
  1544. function _updatemintimer()
  1545. {
  1546. $timerarray = array();
  1547. foreach ($this->_timehandler as $values) {
  1548. $timerarray[] = $values->interval;
  1549. }
  1550. $result = array_multisort($timerarray, SORT_NUMERIC, SORT_ASC);
  1551. if ($result == true && isset($timerarray[0])) {
  1552. $this->_mintimer = $timerarray[0];
  1553. } else {
  1554. $this->_mintimer = false;
  1555. }
  1556. }
  1557. /**
  1558. * reorders the actionhandler array, needed after removing one
  1559. *
  1560. * @return void
  1561. * @access private
  1562. */
  1563. function _reorderactionhandler()
  1564. {
  1565. $orderedactionhandler = array();
  1566. foreach ($this->_actionhandler as $value) {
  1567. $orderedactionhandler[] = $value;
  1568. }
  1569. $this->_actionhandler = &$orderedactionhandler;
  1570. }
  1571. /**
  1572. * reorders the timehandler array, needed after removing one
  1573. *
  1574. * @return void
  1575. * @access private
  1576. */
  1577. function _reordertimehandler()
  1578. {
  1579. $orderedtimehandler = array();
  1580. foreach ($this->_timehandler as $value) {
  1581. $orderedtimehandler[] = $value;
  1582. }
  1583. $this->_timehandler = &$orderedtimehandler;
  1584. }
  1585. /**
  1586. * reorders the modules array, needed after removing one
  1587. *
  1588. * @return void
  1589. * @access private
  1590. */
  1591. function _reordermodules()
  1592. {
  1593. $orderedmodules = array();
  1594. foreach ($this->_modules as $value) {
  1595. $orderedmodules[] = $value;
  1596. }
  1597. $this->_modules = &$orderedmodules;
  1598. }
  1599. /**
  1600. * determines the messagetype of $line
  1601. *
  1602. * Analyses the type of an IRC message and returns the type.
  1603. *
  1604. * @param string $line
  1605. * @return integer SMARTIRC_TYPE_* constant
  1606. * @access private
  1607. */
  1608. function _gettype($line)
  1609. {
  1610. if (preg_match('/^:[^ ]+? [0-9]{3} .+$/', $line) == 1) {
  1611. $lineex = explode(' ', $line);
  1612. $code = $lineex[1];
  1613. switch ($code) {
  1614. case SMARTIRC_RPL_WELCOME:
  1615. case SMARTIRC_RPL_YOURHOST:
  1616. case SMARTIRC_RPL_CREATED:
  1617. case SMARTIRC_RPL_MYINFO:
  1618. case SMARTIRC_RPL_BOUNCE:
  1619. return SMARTIRC_TYPE_LOGIN;
  1620. case SMARTIRC_RPL_LUSERCLIENT:
  1621. case SMARTIRC_RPL_LUSEROP:
  1622. case SMARTIRC_RPL_LUSERUNKNOWN:
  1623. case SMARTIRC_RPL_LUSERME:
  1624. case SMARTIRC_RPL_LUSERCHANNELS:
  1625. return SMARTIRC_TYPE_INFO;
  1626. case SMARTIRC_RPL_MOTDSTART:
  1627. case SMARTIRC_RPL_MOTD:
  1628. case SMARTIRC_RPL_ENDOFMOTD:
  1629. return SMARTIRC_TYPE_MOTD;
  1630. case SMARTIRC_RPL_NAMREPLY:
  1631. case SMARTIRC_RPL_ENDOFNAMES:
  1632. return SMARTIRC_TYPE_NAME;
  1633. case SMARTIRC_RPL_WHOREPLY:
  1634. case SMARTIRC_RPL_ENDOFWHO:
  1635. return SMARTIRC_TYPE_WHO;
  1636. case SMARTIRC_RPL_LISTSTART:
  1637. return SMARTIRC_TYPE_NONRELEVANT;
  1638. case SMARTIRC_RPL_LIST:
  1639. case SMARTIRC_RPL_LISTEND:
  1640. return SMARTIRC_TYPE_LIST;
  1641. case SMARTIRC_RPL_BANLIST:
  1642. case SMARTIRC_RPL_ENDOFBANLIST:
  1643. return SMARTIRC_TYPE_BANLIST;
  1644. case SMARTIRC_RPL_TOPIC:
  1645. return SMARTIRC_TYPE_TOPIC;
  1646. case SMARTIRC_RPL_WHOISUSER:
  1647. case SMARTIRC_RPL_WHOISSERVER:
  1648. case SMARTIRC_RPL_WHOISOPERATOR:
  1649. case SMARTIRC_RPL_WHOISIDLE:
  1650. case SMARTIRC_RPL_ENDOFWHOIS:
  1651. case SMARTIRC_RPL_WHOISCHANNELS:
  1652. return SMARTIRC_TYPE_WHOIS;
  1653. case SMARTIRC_RPL_WHOWASUSER:
  1654. case SMARTIRC_RPL_ENDOFWHOWAS:
  1655. return SMARTIRC_TYPE_WHOWAS;
  1656. case SMARTIRC_RPL_UMODEIS:
  1657. return SMARTIRC_TYPE_USERMODE;
  1658. case SMARTIRC_RPL_CHANNELMODEIS:
  1659. return SMARTIRC_TYPE_CHANNELMODE;
  1660. case SMARTIRC_ERR_NICKNAMEINUSE:
  1661. case SMARTIRC_ERR_NOTREGISTERED:
  1662. return SMARTIRC_TYPE_ERROR;
  1663. default:
  1664. $this->log(SMARTIRC_DEBUG_IRCMESSAGES, 'DEBUG_IRCMESSAGES: replycode UNKNOWN ('.$code.'): "'.$line.'"', __FILE__, __LINE__);
  1665. }
  1666. }
  1667. if (preg_match('/^:.*? PRIVMSG .* :'.chr(1).'ACTION .*'.chr(1).'$/', $line) == 1) {
  1668. return SMARTIRC_TYPE_ACTION;
  1669. } else if (preg_match('/^:.*? PRIVMSG .* :'.chr(1).'.*'.chr(1).'$/', $line) == 1) {
  1670. return SMARTIRC_TYPE_CTCP;
  1671. } else if (preg_match('/^:.*? PRIVMSG (\&|\#|\+|\!).* :.*$/', $line) == 1) {
  1672. return SMARTIRC_TYPE_CHANNEL;
  1673. } else if (preg_match('/^:.*? PRIVMSG .*:.*$/', $line) == 1) {
  1674. return SMARTIRC_TYPE_QUERY;
  1675. } else if (preg_match('/^:.*? NOTICE .* :.*$/', $line) == 1) {
  1676. return SMARTIRC_TYPE_NOTICE;
  1677. } else if (preg_match('/^:.*? INVITE .* .*$/', $line) == 1) {
  1678. return SMARTIRC_TYPE_INVITE;
  1679. } else if (preg_match('/^:.*? JOIN .*$/', $line) == 1) {
  1680. return SMARTIRC_TYPE_JOIN;
  1681. } else if (preg_match('/^:.*? TOPIC .* :.*$/', $line) == 1) {
  1682. return SMARTIRC_TYPE_TOPICCHANGE;
  1683. } else if (preg_match('/^:.*? NICK .*$/', $line) == 1) {
  1684. return SMARTIRC_TYPE_NICKCHANGE;
  1685. } else if (preg_match('/^:.*? KICK .* .*$/', $line) == 1) {
  1686. return SMARTIRC_TYPE_KICK;
  1687. } else if (preg_match('/^:.*? PART .*$/', $line) == 1) {
  1688. return SMARTIRC_TYPE_PART;
  1689. } else if (preg_match('/^:.*? MODE .* .*$/', $line) == 1) {
  1690. return SMARTIRC_TYPE_MODECHANGE;
  1691. } else if (preg_match('/^:.*? QUIT :.*$/', $line) == 1) {
  1692. return SMARTIRC_TYPE_QUIT;
  1693. } else {
  1694. $this->log(SMARTIRC_DEBUG_MESSAGETYPES, 'DEBUG_MESSAGETYPES: SMARTIRC_TYPE_UNKNOWN!: "'.$line.'"', __FILE__, __LINE__);
  1695. return SMARTIRC_TYPE_UNKNOWN;
  1696. }
  1697. }
  1698. /**
  1699. * updates the current connection state
  1700. *
  1701. * @return boolean
  1702. * @access private
  1703. */
  1704. function _updatestate()
  1705. {
  1706. $rtype = get_resource_type($this->_socket);
  1707. if ((is_resource($this->_socket)) &&
  1708. ($this->_socket !== false) &&
  1709. ($rtype == 'socket' || $rtype == 'Socket' || $rtype == 'stream')) {
  1710. $this->_state = true;
  1711. return true;
  1712. } else {
  1713. $this->_state = false;
  1714. $this->_loggedin = false;
  1715. return false;
  1716. }
  1717. }
  1718. /**
  1719. * returns the current connection state
  1720. *
  1721. * @return integer SMARTIRC_STATE_CONNECTED or SMARTIRC_STATE_DISCONNECTED
  1722. * @access private
  1723. */
  1724. function _state()
  1725. {
  1726. $result = $this->_updatestate();
  1727. if ($result == true) {
  1728. return SMARTIRC_STATE_CONNECTED;
  1729. } else {
  1730. return SMARTIRC_STATE_DISCONNECTED;
  1731. }
  1732. }
  1733. /**
  1734. * tries to find a messagehandler for the received message ($ircdata) and calls it
  1735. *
  1736. * @param string $messagecode
  1737. * @param object $ircdata
  1738. * @return void
  1739. * @access private
  1740. */
  1741. function _handlemessage($messagecode, &$ircdata)
  1742. {
  1743. $found = false;
  1744. if (is_numeric($messagecode)) {
  1745. if (!array_key_exists($messagecode, $this->nreplycodes)) {
  1746. $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: ignoring unreconzied messagecode! "'.$messagecode.'"', __FILE__, __LINE__);
  1747. $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: this IRC server ('.$this->_address.') doesn\'t conform to the RFC 2812!', __FILE__, __LINE__);
  1748. return;
  1749. }
  1750. $methodname = 'event_'.strtolower($this->nreplycodes[$messagecode]);
  1751. $_methodname = '_'.$methodname;
  1752. $_codetype = 'by numeric';
  1753. } else if (is_string($messagecode)) { // its not numericcode so already a name/string
  1754. $methodname = 'event_'.strtolower($messagecode);
  1755. $_methodname = '_'.$methodname;
  1756. $_codetype = 'by string';
  1757. }
  1758. // if exists call internal method for the handling
  1759. if (@method_exists($this, $_methodname)) {
  1760. $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: calling internal method "'.get_class($this).'->'.$_methodname.'" ('.$_codetype.')', __FILE__, __LINE__);
  1761. $this->$_methodname($ircdata);
  1762. $found = true;
  1763. }
  1764. // if exist, call user defined method for the handling
  1765. if (@method_exists($this, $methodname)) {
  1766. $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: calling user defined method "'.get_class($this).'->'.$methodname.'" ('.$_codetype.')', __FILE__, __LINE__);
  1767. $this->$methodname($ircdata);
  1768. $found = true;
  1769. }
  1770. if ($found == false) {
  1771. $this->log(SMARTIRC_DEBUG_MESSAGEHANDLER, 'DEBUG_MESSAGEHANDLER: no method found for "'.$messagecode.'" ('.$methodname.')', __FILE__, __LINE__);
  1772. }
  1773. }
  1774. /**
  1775. * tries to find a actionhandler for the received message ($ircdata) and calls it
  1776. *
  1777. * @param object $ircdata
  1778. * @return void
  1779. * @access private
  1780. */
  1781. function _handleactionhandler(&$ircdata)
  1782. {
  1783. $handler = &$this->_actionhandler;
  1784. $handlercount = count($handler);
  1785. for ($i = 0; $i < $handlercount; $i++) {
  1786. $handlerobject = &$handler[$i];
  1787. if (substr($handlerobject->message, 0, 1) == '/') {
  1788. $regex = $handlerobject->message;
  1789. } else {
  1790. $regex = '/'.$handlerobject->message.'/';
  1791. }
  1792. if (($handlerobject->type & $ircdata->type) &&
  1793. (preg_match($regex, $ircdata->message) == 1)) {
  1794. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: actionhandler match found for id: '.$i.' type: '.$ircdata->type.' message: "'.$ircdata->message.'" regex: "'.$regex.'"', __FILE__, __LINE__);
  1795. $methodobject = &$handlerobject->object;
  1796. $method = $handlerobject->method;
  1797. if (@method_exists($methodobject, $method)) {
  1798. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: calling method "'.get_class($methodobject).'->'.$method.'"', __FILE__, __LINE__);
  1799. $methodobject->$method($this, $ircdata);
  1800. } else {
  1801. $this->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: method doesn\'t exist! "'.get_class($methodobject).'->'.$method.'"', __FILE__, __LINE__);
  1802. }
  1803. break;
  1804. }
  1805. }
  1806. }
  1807. /**
  1808. * getting current microtime, needed for benchmarks
  1809. *
  1810. * @return float
  1811. * @access private
  1812. */
  1813. function _microint()
  1814. {
  1815. $tmp = microtime();
  1816. $parts = explode(' ', $tmp);
  1817. $floattime = (float)$parts[0] + (float)$parts[1];
  1818. return $floattime;
  1819. }
  1820. /**
  1821. * adds an user to the channelobject or updates his info
  1822. *
  1823. * @param object $channel
  1824. * @param object $newuser
  1825. * @return void
  1826. * @access private
  1827. */
  1828. function _adduser(&$channel, &$newuser)
  1829. {
  1830. $lowerednick = strtolower($newuser->nick);
  1831. if (isset($channel->users[$lowerednick])) {
  1832. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: updating user: '.$newuser->nick.' on channel: '.$channel->name, __FILE__, __LINE__);
  1833. // lets update the existing user
  1834. $currentuser = &$channel->users[$lowerednick];
  1835. if ($newuser->ident !== null) {
  1836. $currentuser->ident = $newuser->ident;
  1837. }
  1838. if ($newuser->host !== null) {
  1839. $currentuser->host = $newuser->host;
  1840. }
  1841. if ($newuser->realname !== null) {
  1842. $currentuser->realname = $newuser->realname;
  1843. }
  1844. if ($newuser->op !== null) {
  1845. $currentuser->op = $newuser->op;
  1846. }
  1847. if ($newuser->voice !== null) {
  1848. $currentuser->voice = $newuser->voice;
  1849. }
  1850. if ($newuser->ircop !== null) {
  1851. $currentuser->ircop = $newuser->ircop;
  1852. }
  1853. if ($newuser->away !== null) {
  1854. $currentuser->away = $newuser->away;
  1855. }
  1856. if ($newuser->server !== null) {
  1857. $currentuser->server = $newuser->server;
  1858. }
  1859. if ($newuser->hopcount !== null) {
  1860. $currentuser->hopcount = $newuser->hopcount;
  1861. }
  1862. } else {
  1863. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: adding user: '.$newuser->nick.' to channel: '.$channel->name, __FILE__, __LINE__);
  1864. // he is new just add the reference to him
  1865. $channel->users[$lowerednick] = &$newuser;
  1866. }
  1867. $user = &$channel->users[$lowerednick];
  1868. if ($user->op) {
  1869. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: adding op: '.$user->nick.' to channel: '.$channel->name, __FILE__, __LINE__);
  1870. $channel->ops[$user->nick] = true;
  1871. }
  1872. if ($user->voice) {
  1873. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: adding voice: '.$user->nick.' to channel: '.$channel->name, __FILE__, __LINE__);
  1874. $channel->voices[$user->nick] = true;
  1875. }
  1876. }
  1877. /**
  1878. * removes an user from one channel or all if he quits
  1879. *
  1880. * @param object $ircdata
  1881. * @return void
  1882. * @access private
  1883. */
  1884. function _removeuser(&$ircdata)
  1885. {
  1886. if ($ircdata->type & (SMARTIRC_TYPE_PART|SMARTIRC_TYPE_QUIT)) {
  1887. $nick = $ircdata->nick;
  1888. } else if ($ircdata->type & SMARTIRC_TYPE_KICK) {
  1889. $nick = $ircdata->rawmessageex[3];
  1890. } else {
  1891. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: unknown TYPE ('.$ircdata->type.') in _removeuser(), trying default', __FILE__, __LINE__);
  1892. $nick = $ircdata->nick;
  1893. }
  1894. $lowerednick = strtolower($nick);
  1895. if ($this->_nick == $nick) {
  1896. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: we left channel: '.$ircdata->channel.' destroying...', __FILE__, __LINE__);
  1897. unset($this->_channels[strtolower($ircdata->channel)]);
  1898. } else {
  1899. if ($ircdata->type & SMARTIRC_TYPE_QUIT) {
  1900. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: user '.$nick.' quit, removing him from all channels', __FILE__, __LINE__);
  1901. // remove the user from all channels
  1902. foreach ($this->_channels as $channelkey => $channelvalue) {
  1903. // loop through all channels
  1904. $channel = &$this->_channels[$channelkey];
  1905. foreach ($channel->users as $userkey => $uservalue) {
  1906. // loop through all user in this channel
  1907. if ($nick == $uservalue->nick) {
  1908. // found him
  1909. // kill him
  1910. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: found him on channel: '.$channel->name.' destroying...', __FILE__, __LINE__);
  1911. unset($channel->users[$lowerednick]);
  1912. if (isset($channel->ops[$nick])) {
  1913. // die!
  1914. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: removing him from op list', __FILE__, __LINE__);
  1915. unset($channel->ops[$nick]);
  1916. }
  1917. if (isset($channel->voices[$nick])) {
  1918. // die!!
  1919. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: removing him from voice list', __FILE__, __LINE__);
  1920. unset($channel->voices[$nick]);
  1921. }
  1922. // ups this was not DukeNukem 3D
  1923. }
  1924. }
  1925. }
  1926. } else {
  1927. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: removing user: '.$nick.' from channel: '.$ircdata->channel, __FILE__, __LINE__);
  1928. $channel = &$this->_channels[strtolower($ircdata->channel)];
  1929. unset($channel->users[$lowerednick]);
  1930. if (isset($channel->ops[$nick])) {
  1931. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: removing him from op list', __FILE__, __LINE__);
  1932. unset($channel->ops[$nick]);
  1933. }
  1934. if (isset($channel->voices[$nick])) {
  1935. $this->log(SMARTIRC_DEBUG_CHANNELSYNCING, 'DEBUG_CHANNELSYNCING: removing him from voice list', __FILE__, __LINE__);
  1936. unset($channel->voices[$nick]);
  1937. }
  1938. }
  1939. }
  1940. }
  1941. /**
  1942. * @return void
  1943. * @access private
  1944. */
  1945. function _checkPHPVersion()
  1946. {
  1947. // doing nothing at the moment
  1948. }
  1949. /**
  1950. * checks if the passed handlertype is valid
  1951. *
  1952. * @param integer $handlertype
  1953. * @return boolean
  1954. * @access private
  1955. */
  1956. function _isValidType($handlertype) {
  1957. if ($handlertype & SMARTIRC_TYPE_ALL ) {
  1958. return true;
  1959. } else {
  1960. return false;
  1961. }
  1962. }
  1963. // </private methods>
  1964. function isError($object) {
  1965. return (bool)(is_object($object) && (strtolower(get_class($object)) == 'net_smartirc_error'));
  1966. }
  1967. function &throwError($message) {
  1968. return new Net_SmartIRC_Error($message);
  1969. }
  1970. }
  1971. class Net_SmartIRC extends Net_SmartIRC_messagehandler
  1972. {
  1973. // empty
  1974. }
  1975. /**
  1976. * @access public
  1977. */
  1978. class Net_SmartIRC_data
  1979. {
  1980. /**
  1981. * @var string
  1982. * @access public
  1983. */
  1984. var $from;
  1985. /**
  1986. * @var string
  1987. * @access public
  1988. */
  1989. var $nick;
  1990. /**
  1991. * @var string
  1992. * @access public
  1993. */
  1994. var $ident;
  1995. /**
  1996. * @var string
  1997. * @access public
  1998. */
  1999. var $host;
  2000. /**
  2001. * @var string
  2002. * @access public
  2003. */
  2004. var $channel;
  2005. /**
  2006. * @var string
  2007. * @access public
  2008. */
  2009. var $message;
  2010. /**
  2011. * @var array
  2012. * @access public
  2013. */
  2014. var $messageex = array();
  2015. /**
  2016. * @var integer
  2017. * @access public
  2018. */
  2019. var $type;
  2020. /**
  2021. * @var string
  2022. * @access public
  2023. */
  2024. var $rawmessage;
  2025. /**
  2026. * @var array
  2027. * @access public
  2028. */
  2029. var $rawmessageex = array();
  2030. }
  2031. /**
  2032. * @access public
  2033. */
  2034. class Net_SmartIRC_actionhandler
  2035. {
  2036. /**
  2037. * @var integer
  2038. * @access public
  2039. */
  2040. var $id;
  2041. /**
  2042. * @var integer
  2043. * @access public
  2044. */
  2045. var $type;
  2046. /**
  2047. * @var string
  2048. * @access public
  2049. */
  2050. var $message;
  2051. /**
  2052. * @var object
  2053. * @access public
  2054. */
  2055. var $object;
  2056. /**
  2057. * @var string
  2058. * @access public
  2059. */
  2060. var $method;
  2061. }
  2062. /**
  2063. * @access public
  2064. */
  2065. class Net_SmartIRC_timehandler
  2066. {
  2067. /**
  2068. * @var integer
  2069. * @access public
  2070. */
  2071. var $id;
  2072. /**
  2073. * @var integer
  2074. * @access public
  2075. */
  2076. var $interval;
  2077. /**
  2078. * @var integer
  2079. * @access public
  2080. */
  2081. var $lastmicrotimestamp;
  2082. /**
  2083. * @var object
  2084. * @access public
  2085. */
  2086. var $object;
  2087. /**
  2088. * @var string
  2089. * @access public
  2090. */
  2091. var $method;
  2092. }
  2093. /**
  2094. * @access public
  2095. */
  2096. class Net_SmartIRC_channel
  2097. {
  2098. /**
  2099. * @var string
  2100. * @access public
  2101. */
  2102. var $name;
  2103. /**
  2104. * @var string
  2105. * @access public
  2106. */
  2107. var $key;
  2108. /**
  2109. * @var array
  2110. * @access public
  2111. */
  2112. var $users = array();
  2113. /**
  2114. * @var array
  2115. * @access public
  2116. */
  2117. var $ops = array();
  2118. /**
  2119. * @var array
  2120. * @access public
  2121. */
  2122. var $voices = array();
  2123. /**
  2124. * @var array
  2125. * @access public
  2126. */
  2127. var $bans = array();
  2128. /**
  2129. * @var string
  2130. * @access public
  2131. */
  2132. var $topic;
  2133. /**
  2134. * @var string
  2135. * @access public
  2136. */
  2137. var $mode;
  2138. }
  2139. /**
  2140. * @access public
  2141. */
  2142. class Net_SmartIRC_user
  2143. {
  2144. /**
  2145. * @var string
  2146. * @access public
  2147. */
  2148. var $nick;
  2149. /**
  2150. * @var string
  2151. * @access public
  2152. */
  2153. var $ident;
  2154. /**
  2155. * @var string
  2156. * @access public
  2157. */
  2158. var $host;
  2159. /**
  2160. * @var string
  2161. * @access public
  2162. */
  2163. var $realname;
  2164. /**
  2165. * @var boolean
  2166. * @access public
  2167. */
  2168. var $ircop;
  2169. /**
  2170. * @var boolean
  2171. * @access public
  2172. */
  2173. var $away;
  2174. /**
  2175. * @var string
  2176. * @access public
  2177. */
  2178. var $server;
  2179. /**
  2180. * @var integer
  2181. * @access public
  2182. */
  2183. var $hopcount;
  2184. }
  2185. /**
  2186. * @access public
  2187. */
  2188. class Net_SmartIRC_channeluser extends Net_SmartIRC_user
  2189. {
  2190. /**
  2191. * @var boolean
  2192. * @access public
  2193. */
  2194. var $op;
  2195. /**
  2196. * @var boolean
  2197. * @access public
  2198. */
  2199. var $voice;
  2200. }
  2201. /**
  2202. * @access public
  2203. */
  2204. class Net_SmartIRC_ircuser extends Net_SmartIRC_user
  2205. {
  2206. /**
  2207. * @var array
  2208. * @access public
  2209. */
  2210. var $joinedchannels = array();
  2211. }
  2212. /**
  2213. * @access public
  2214. */
  2215. class Net_SmartIRC_listenfor
  2216. {
  2217. /**
  2218. * @var array
  2219. * @access public
  2220. */
  2221. var $result = array();
  2222. /**
  2223. * stores the received answer into the result array
  2224. *
  2225. * @param object $irc
  2226. * @param object $ircdata
  2227. * @return void
  2228. */
  2229. function handler(&$irc, &$ircdata)
  2230. {
  2231. $irc->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: listenfor handler called', __FILE__, __LINE__);
  2232. $this->result[] = $ircdata->message;
  2233. $irc->disconnect(true);
  2234. }
  2235. }
  2236. // so we don't break BC!
  2237. /**
  2238. * @access public
  2239. */
  2240. class Net_SmartIRC_objListenFor
  2241. {
  2242. /**
  2243. * @var array
  2244. * @access public
  2245. */
  2246. var $result = array();
  2247. /**
  2248. * stores the received answer into the result array
  2249. *
  2250. * @param object $irc
  2251. * @param object $ircdata
  2252. * @return void
  2253. */
  2254. function handler(&$irc, &$ircdata)
  2255. {
  2256. $irc->log(SMARTIRC_DEBUG_ACTIONHANDLER, 'DEBUG_ACTIONHANDLER: objListenFor handler called', __FILE__, __LINE__);
  2257. $this->result[] = $ircdata;
  2258. $irc->disconnect(true);
  2259. }
  2260. }
  2261. class Net_SmartIRC_Error
  2262. {
  2263. var $error_msg;
  2264. function Net_SmartIRC_Error($message)
  2265. {
  2266. $this->error_msg = $message;
  2267. }
  2268. function getMessage()
  2269. {
  2270. return $this->error_msg;
  2271. }
  2272. }
  2273. ?>