Location: PHPKode > projects > Nzbirc > nzbirc-1.4/worker.php
<?php

/**************************************************
 * NZBirc v1
 * Copyright (c) 2006 Harry Bragg
 * tiberious.org
 * Worker Thread
 **************************************************
 *
 * Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
// ------- PHP code ----------
require_once 'SmartIRC/defines.php';

if ( isset( $argv[1] ) )
{
	$userPath = realpath($argv[1]);
}

$inc = false;
if ( isset( $userPath ) )
{
	if ( is_dir( $userPath ) )
	{
		if ( ( strlen( $userPath ) > 0 ) &&
		     ( substr( $userPath, -1) != '/' ) )
		{
			$userPath = $userPath.'/';
		}
		if ( file_exists( $userPath.'config.inc.php') )
		{
			include_once( $userPath.'config.inc.php' );
			$inc = true;
		}
	}
}

if ( !$inc )
{
	exit('Something went wrong, config file not included');
}

/**
 * @access public
 */
class worker
{
	/**
	 * @var string
	 * @access private
	 */
	var $_phpPath = '';

	/**
	 * @var bool
	 * @access public
	 */
	var $isWorker = true;

	/**
	 * List of configuration options
	 */
	var $config = array();

    /**
     * @var array
     * @access private
     */
    var $_timehandler = array();

    /**
     * @var integer
     * @access private
     */
    var $_debug = SMARTIRC_DEBUG_NOTICE;

    /**
     * @var integer
     * @access private
     */
    var $_logdestination = SMARTIRC_STDOUT;

    /**
     * @var mixed
     * @access private
     */
    var $_mintimer = false;
    
    /**
     * @var integer
     * @access private
     */
    var $_maxtimer = 300000;
    
    /**
     * @var resource
     * @access private
     */
    var $_logfilefp = 0;
    
    /**
     * @var string
     * @access private
     */
    var $_logfile = 'Net_SmartIRC.log';

    /**
     * @var integer
     * @access private
     */
    var $_timehandlerid = 0;

    /**
     * Stores the path to the modules that can be loaded.
     *
     * @var string
     * @access privat
     */
    var $_modulepath = '';
    
    /**
     * Stores all objects of the modules.
     *
     * @var string
     * @access privat
     */
    var $_modules = array();

	/**
	 * Module definitions
	 *
	 * @var array
	 * @access private
	 */
	var $_modDef = array(
		'base' => array(),
		'tvrage' => array(
			'includes' => array(
				'HTTP/Request.php' ),
			'depends' => array(
				'func',
				'base',
				'store' ),
		),
		'ed' => array(
			'depends' => array(
				'tvrage',
				'func',
				'base',
				'imdb' ),
		),
		'func' => array(),
		'hella' => array(
			'includes' => array(
				'XML/RPC.php' ),
			'extensions' => array(
				'xml' ),
			'depends' => array(
				'func',
				'base',
				'store' )
		),
		'nzb' => array(
			'includes' => array(
				'HTTP/Request.php' ),
			'depends' => array(
				'tvrage',
				'ed',
				'func',
				'base',
				'store' )
		),
		'store' => array(
			'includes' => array(
				'XML/Serializer.php',
				'XML/Unserializer.php' ),
			'extensions' => array(
				'xml'
			)
		),
		'config' => array(),
		'autotv' => array(
			'depends' => array(
				'tvrage',
				'nzb',
				'store',
				'base',
				'func'
			)
		),
		'autoquery' => array(
			'depends' => array(
				'nzb',
				'store',
				'base',
				'func'
			)
		),
		'tvnzb' => array(
			'includes' => array(
				'HTTP/Request.php' ),		
			'depends' => array(
				'tvrage',
				'store',
				'base',
				'func'
			)
		),
		'nzbv2' => array(
			'includes' => array(
				'HTTP/Request.php' ),		
			'depends' => array(
				'tvrage',
				'store',
				'base',
				'func',
				'ed'
			)
		),
		'imdb' => array(
			'depends' => array(
				'base',
				'func',
				'store'
			)
		)
	);

	function worker()
	{
        ob_implicit_flush(true);
        @set_time_limit(0);
        ignore_user_abort(true);

        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);
        }		
	}
	
	/**
	 * Setup
	 *
	 * @access public
	 * @return void
	 */
	function setup()
	{	
		global $config;
		
		$this->config = $config;
		
		// setup the irc connection
		
		ini_set( 'memory_limit', $this->config->memoryAllocation.'M' );		

		$this->setLogdestination( SMARTIRC_FILE );
		$this->setLogfile( $this->config->debugLogPath );
		$this->setModulepath( $this->config->modulePath );
		$this->setPhpPath( $this->config->phpPath );
		$this->setDebug( SMARTIRC_DEBUG_MODULES | SMARTIRC_DEBUG_ACTIONHANDLER | SMARTIRC_DEBUG_NOTICE );
		//$this->setDebug( SMARTIRC_DEBUG_ALL );
		
		// check custom extensions
		foreach( $this->config->extensions as $ext ) {
			$this->checkExtension( $ext );
		}

		$this->loadModules();
		
		if ( strlen( $this->config->workerPidPath ) == 0 )
			$this->config->workerPidPath = $this->config->userPath.'worker.pid';
		$fp = fopen( $this->config->workerPidPath, 'w+' );
		if ( $fp )
		{
			fwrite( $fp, getmypid() );
			fflush( $fp );
			fclose( $fp );
		}
		else 
		{
			$this->log( SMARTIRC_DEBUG_NOTICE, 'DEBUG_WORKER: Oh dear, cant open pid file, please check config [workerPidPath]', __FILE__, __LINE__ );
			exit('DEBUG_WORKER: Oh dear, cant open pid file, please check config [workerPidPath]');
		}		
		$this->log( SMARTIRC_DEBUG_NOTICE, 'DEBUG_WORKER: Worker Thread running with PID: '.getmypid(), __FILE__, __LINE__ );
		
		$this->listen();
	}

	function listen()
	{
		while( true )
		{
			// do stuff
			$this->_checktimer();
			
			// sleep 10 sec
			sleep(10);
		}
	}
	
	/*******************************************************
	 * A Couple of Overrides
	 *******************************************************/
	
	function setPhpPath( $path )
	{
		$this->_phpPath = $path;
	} 

    /**
     * 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;
    }

	/**
	 * Check if an extension is loaded, if not... load it
	 *
	 * @access public
	 * @return bool
	 */
	function checkExtension( $name )
	{		
		if (extension_loaded($name)) {
			return true;
		}
		else
		{
			$this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: '.$name.' extension not loaded, trying to load it...', __FILE__, __LINE__);
			// attempt to load the module
			
			if (strtoupper(substr(PHP_OS, 0,3) == 'WIN')) {
				$load_status = @dl('php_'.$name.'.dll');
			} else {
				$load_status = @dl($name.'.so');
			}
			
			if ($load_status)
			{
				$this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: '.$name.' extension sucessfully loaded', __FILE__, __LINE__ );				
				return true;
			} else
			{
				$this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING: '.$name.' extension failed to load', __FILE__, __LINE__ );
				return false;
			}
		}
	}

    /**
     * getting current microtime, needed for benchmarks
     *
     * @return float
     * @access private
     */
    function _microint()
    {
        $tmp = microtime();
        $parts = explode(' ', $tmp);
        $floattime = (float)$parts[0] + (float)$parts[1];
        return $floattime;
    }
	
	/*******************************************************
	 * Module code
	 *******************************************************/
	
	/**
	 * Loads a module
	 * 1. Checks the config to see if it is listed
	 * 2. checks to see if it has any dependencies
	 * 3. checks to see if needs any extensions
	 * 4. checks to see if it has any includes
	 * 5. loads the module
	 *
	 * @param string $name - String input
	 * @return void
	 * @access public
	 */
    function loadModule($name)
    {

        // is the module already loaded?
        if ( $this->isLoadedModule( $name ) )
		{
            $this->log(SMARTIRC_DEBUG_NOTICE, 'WARNING! module with the name "'.$name.'" already loaded!', __FILE__, __LINE__);
            return false;
        }
        
        $filename = $this->_modulepath.'/'.$name.'.php';
        if (!file_exists($filename))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: couldn\'t load module "'.$filename.'" file doesn\'t exist', __FILE__, __LINE__);
            return false;
        }
		
		// check module definition
		if ( isset( $this->_modDef[$name] ) )
		{

			// check the dependencies
			if ( is_array( $this->_modDef[$name]['depends'] ) ) {
				foreach( $this->_modDef[$name]['depends'] as $depName ) {
					if ( !$this->isLoadedModule( $depName ) )
					{
						// load the module first
						$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: [Module: '.$name.'] depends on module: '.$depName.', loading that module first', __FILE__, __LINE__);
						if ( !$this->loadModule( $depName ) )
						{
							$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: [Module: '.$name.'] Can no load as it depends on '.$depName, __FILE__, __LINE__);
							return false;
						}
					}
				}
			}
		 
			// check extensions 		
			if ( is_array( $this->_modDef[$name]['extensions'] ) ) {
				foreach( $this->_modDef[$name]['extensions'] as $ext ) {
					if ( !@extension_loaded( $ext ) ) {
						if ( $this->checkExtension( $ext ) ) {
							$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: [Module: '.$name.'] included extension: '.$ext, __FILE__, __LINE__);
						} else {
							$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: [Module: '.$name.'] extension: '.$ext.' failed to load', __FILE__, __LINE__);	
						}
					}
				}
			}
			
			// check includes
			if ( is_array( $this->_modDef[$name]['includes'] ) ) {
				foreach( $this->_modDef[$name]['includes'] as $file ) {
					if ( !in_array( $file, get_included_files()) )
					{
						include_once( $file );
						$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: [Module: '.$name.'] included file: '.$file, __FILE__, __LINE__);						
					}
				}
			}
						
		}
		
		
		if ( !empty( $this->_phpPath ) )
		{  
			// check to see if the file compiles using php -l
			$ret = exec($this->_phpPath.' -l '.$filename, $output);
			if (!preg_match('/^No syntax errors/i', $output[0]))
			{
				$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: couldn\'t load module: "'.$name.'", failed to compile, output:', __FILE__, __LINE__);
				//echo 'DEBUG_MODULES: couldn\'t load module: "'.$name.'", failed to compile, output:'."\n";
				foreach( $output as $string )
				{
					$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: '.$string, __FILE__, __LINE__);
					//echo 'DEBUG_MODULES: '.$string."\n";
				}
				return $output;
			}
		}
		
        $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: loading module: "'.$name.'"...', __FILE__, __LINE__);		
        
		if (@extension_loaded('runkit')) { 
			runkit_import( $filename ); 
		} else {
			include_once( $filename );
		}
        $classname = 'Net_SmartIRC_module_'.$name;
        
        if (!class_exists($classname))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: class '.$classname.' not found in '.$filename, __FILE__, __LINE__);
            return false;
        }
        
        $methods = get_class_methods($classname);
        if (!in_array('module_init', $methods))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: required method'.$classname.'::module_init not found, aborting...', __FILE__, __LINE__);
            return false;
        }
        
        if (!in_array('module_exit', $methods))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: required method'.$classname.'::module_exit not found, aborting...', __FILE__, __LINE__);
            return false;
        }
        
        $vars = array_keys(get_class_vars($classname));
        if (!in_array('name', $vars))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: required variable '.$classname.'::name not found, aborting...', __FILE__, __LINE__);
            return false;
        }
        
        if (!in_array('description', $vars))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: required variable '.$classname.'::description not found, aborting...', __FILE__, __LINE__);
            return false;
        }
        
        if (!in_array('author', $vars))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: required variable '.$classname.'::author not found, aborting...', __FILE__, __LINE__);
            return false;
        }
        
        if (!in_array('license', $vars))
		{
            $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: required variable '.$classname.'::license not found, aborting...', __FILE__, __LINE__);
            return false;
        }
        
        // looks like the module satisfies us
        $module = &new $classname;
        $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: successful created instance of: '.$classname, __FILE__, __LINE__);
        
        $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: calling '.$classname.'::module_init()', __FILE__, __LINE__);
        $module->module_init($this);
        $this->_modules[$name] = &$module;
        
        $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: successful loaded module: '.$name, __FILE__, __LINE__);
        return true;
    }
    
    function unloadModule($name)
    {
        $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: unloading module: '.$name.'...', __FILE__, __LINE__);
        
        foreach( $this->_modules as $modName => $modVals )
        {
            if ($modName == $name)
			{
                $this->_modules[$modName]->module_exit($this);
                unset( $this->_modules[$name] );
                $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: successfully unloaded module: '.$name, __FILE__, __LINE__);
                return true;
            }
			
		}
        
        $this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: couldn\'t unloaded module: '.$name.' (it\'s not loaded!)', __FILE__, __LINE__);
        return false;
    }	 
	
	/**
	 * Reload a module
	 *
	 * @param string name - Module name
	 * @return string - textual result of the function
	 * @access private
	 */
	function reloadModule( $name )
	{

		$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: reloading module: '.$name.'...', __FILE__, __LINE__);
		
		$this->unloadModule( $name );
		if ( ( $out = $this->loadModule( $name ) ) === true )
		{
			$out = 'Rehash of: '.$name.', successful';
			$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: successful reloaded module: '.$name.'...', __FILE__, __LINE__);
		} else
		{
			$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: failed to reload module: '.$name.' output: ', __FILE__, __LINE__);
			
			if ( is_array( $out ) ) {
				foreach( $out as $line ) {
					$this->log(SMARTIRC_DEBUG_MODULES, 'DEBUG_MODULES: '.$line, __FILE__, __LINE__);
				}	
			}
		}
		return $out;
	}

	/**
	 * Loads the modules (for startup)
	 */
	function loadModules()
	{
		foreach( $this->config->modules as $id => $module )
		{
			$modName = ( is_array( $module ) )? $id:$module;
			$this->loadModule( $modName );
		}
	}
	
	/**
	 * module Debug
	 */
	function modDebug( $module, $msg, $file, $line, $level = SMARTIRC_DEBUG_NOTICE )
	{
		$this->log( $level, sprintf( 'DEBUG_MODULES: [Module: %s] %s', $module, $msg ), $file, $line );
	}
	
	/**
	 * Is the module loaded?
	 *
	 * @param string $name - Name of the module
	 * @return bool
	 * @access public
	 */
	function isLoadedModule( $name )
	{
		if ( isset( $this->_modules[$name] ) )
			return true;
		else
			return false;
	}	

    /**
     * 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:
            case SMARTIRC_STDOUT:
            case SMARTIRC_SYSLOG:
            case SMARTIRC_BROWSEROUT:
            case 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 paths for the modules.
     *
     * @param integer $path
     * @return void
     * @access public
     */
    function setModulepath($path)
    {
        $this->_modulepath = $path;
    }

    /**
     * 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;
        }
        
		list($usec, $sec) = explode(" ", microtime());
		$msec = sprintf( '%03d', $usec * 1000);
        $formatedentry = date('M d H:i:s.').$msec.' {WORKER} '.$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)) {
                    $this->_logfilefp = fopen($this->_logfile,'a+');
                }
                fwrite($this->_logfilefp, $formatedentry);
                fflush($this->_logfilefp);
				fclose($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;
        }
    }


	/*******************************************************
	 * Time Handler Override
	 *******************************************************/
	 
    /**
     * 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, $vars = false)
    {
        $id = $this->_timehandlerid++;
        $newtimehandler = &new Net_SmartIRC_timehandler();
        
        $newtimehandler->id = $id;
        $newtimehandler->interval = $interval;
        $newtimehandler->object = &$object;
        $newtimehandler->method = $methodname;
        $newtimehandler->lastmicrotimestamp = $this->_microint();
		$newtimehandler->vars = $vars;
        
        $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;
    }	
	
   /**
     * Checks the running timers and calls the registered timehandler,
     * when the interval is reached.
     *
     * @return void
     * @access private
     */
    function _checktimer()
    {        
        // 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, $handlerobject->vars);
                }
            }
        }
    }	

    /**
     * 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;
    }

    /**
     * updates _mintimer to the smallest timer interval
     *
     * @return void
     * @access private
     */
    function _updatemintimer()
    {
        $timerarray = array();
        foreach ($this->_timehandler as $values) {
            $timerarray[] = $values->interval;
        }
        
        $result = array_multisort($timerarray, SORT_NUMERIC, SORT_ASC);
        if ($result == true && isset($timerarray[0])) {
            $this->_mintimer = $timerarray[0];
        } else {
            $this->_mintimer = false;
        }
    }

    /**
     * reorders the timehandler array, needed after removing one
     *
     * @return void
     * @access private
     */
    function _reordertimehandler()
    {
        $orderedtimehandler = array();
        foreach ($this->_timehandler as $value) {
            $orderedtimehandler[] = $value;
        }
        $this->_timehandler = &$orderedtimehandler;
    }

	/*****************************************************
	 * Fake command
	 *****************************************************/

    function registerActionhandler($handlertype, $regexhandler, &$object, $methodname)
    {
	}

    function unregisterActionhandler($handlertype, $regexhandler, &$object, $methodname)
    {
	}
	
    function unregisterActionid($id)
    {
	}
	
	function message($type, $destination, $messagearray, $priority = SMARTIRC_MEDIUM)
	{
	}
}



/**
 * @access public
 */
class Net_SmartIRC_timehandler
{
    /**
     * @var integer
     * @access public
     */
    var $id;
    
    /**
     * @var integer
     * @access public
     */
    var $interval;
    
    /**
     * @var integer
     * @access public
     */
    var $lastmicrotimestamp;
    
    /**
     * @var object
     * @access public
     */
    var $object;
    
    /**
     * @var string
     * @access public
     */
    var $method;
	
	/**
	 * We might want to pass variables with the timer too
	 *
	 * @var array
	 * @access public
	 */
	var $vars;
}


/*******************************************************
 * Lets do our own error handling
 *******************************************************/
 
// user defined error handling function
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
	global $irc;
	
	$errortype = array (
		E_ERROR				=> 'Error',
		E_WARNING			=> 'Warning',
		E_PARSE				=> 'Parsing Error',
		E_NOTICE			=> 'Notice',
		E_CORE_ERROR		=> 'Core Error',
		E_CORE_WARNING		=> 'Core Warning',
		E_COMPILE_ERROR		=> 'Compile Error',
		E_COMPILE_WARNING	=> 'Compile Warning',
		E_USER_ERROR		=> 'User Error',
		E_USER_WARNING		=> 'User Warning',
		E_USER_NOTICE		=> 'User Notice',
		E_STRICT			=> 'Runtime Notice',
		E_RECOVERABLE_ERROR	=> 'Catchable Fatal Error'
		);
	
	// set of errors for which a var trace will be saved
	$user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
	
	$dont_report_errors = array(E_NOTICE, E_STRICT);
	//$dont_report_errors = array();
	
	if ( !in_array($errno, $dont_report_errors) )
	{
		$eMsg = "PHP Error\n".
			"Error Number: ".$errno."\n".
			"Error Type: ".$errortype[$errno]."\n".
			"Error Message: ".$errmsg."\n".
			"File Name: ".$filename."\n".
			"Line Number: ".$linenum."\n";
			
		if (in_array($errno, $user_errors)) {
			$eMsg .= "Variable Trace: ".wddx_serialize_value($vars, "Variables") . "\n";
		}
		
		echo $eMsg;
		
		$irc->log( SMARTIRC_DEBUG_NOTICE, $eMsg, __FILE__, __LINE__ );
	}
}

$irc = &new worker();

set_error_handler("userErrorHandler");

$irc->setup();

?>
Return current item: Nzbirc