* @copyright 2005-2006, Tobias Nystrom * @license http://www.gnu.org/copyleft/gpl.html */ /** * Modulehandler Class * * @package bambotoo * @subpackage bambotoo-core */ class modulehandler { /** * Where to look for modules * @var string * @access private */ var $modules_dir = 'modules/'; /** * Array of modules available. modules/ directory is scanned an stored as * array where key=module_name and val is=path/to/module.name.php * @var array * @access private */ var $available_modules; /** * Array of disabled modules available. loaded from config file * @var array * @access private */ var $disabled_modules; /** * ## Main array of loaded modules Objects * @var array * @access private */ var $loaded_modules; /** * Reference to main bot object */ var $_bot; /** * The configuration vars for module loaded from modules.conf */ var $module_config; function modulehandler(&$bot){ $this->_bot = &$bot; } /** * Passed a string of space seperated modules, these are exploded, checked and then loaded * calls loadModule() */ function loadModules($modules_string){ $modules_to_load = helpers::toArray($modules_string); $return_string = 'Modules loaded: '; foreach($modules_to_load as $mod){ if(!array_key_exists($mod,$this->available_modules)){ $return_string .= $mod.' (doesn\'t exist), '; }elseif(array_key_exists($mod,$this->available_modules) && isset($this->loaded_modules[$mod]) ){ $return_string .= $mod.' (already loaded), '; }else{ $return_string .= $this->loadModule($mod); } } $return_string = substr($return_string, 0, -2); $this->_bot->logger->addBotLog($return_string,BB_LOG_MODULE); return $return_string; } /** * Loads a named module */ function loadModule($module){ $mod_file = $this->available_modules[$module]; $return_string = ''; include_once($mod_file); if(isset($this->_bot->modules_config[$module])){ $mod_config = $this->_bot->modules_config[$module]; } else { $mod_config = array(); } $this->loaded_modules[$module] = new $module(); $this->loaded_modules[$module]->__initialise($this->_bot, $mod_config); // Call users initialisation function if it exists eg htmltitle if(method_exists($this->loaded_modules[$module], 'init')){ $this->loaded_modules[$module]->init(); } if(isset($this->loaded_modules[$module]->unloadable)) { //**** Not sure what is happening here if($this->loaded_modules[$module]->unloadable !== false) { $this->loaded_modules[$module]->unloadable = true; } }else{ $this->loaded_modules[$module]->unloadable = true; } if(!isset($this->loaded_modules[$module]->enabled)) { $this->loaded_modules[$module]->enabled = true; } if($this->loaded_modules[$module]->enabled !== false) { $this->loaded_modules[$module]->enabled = true; $return_string = $module . ', '; } else { $return_string .= $module . ' (error), '; unset($this->loaded_modules[$module]); } return $return_string; } /** * Initialse module(s) - this is called at start up and parses the .config variables * @param string $modules String containing space separated list of modulenames * @return string List of modules loaded and not loaded */ function initialise() { $return = array('modules_loaded' => false, 'modules_not_loaded' => false); $modulesLoaded = ''; $modulesNotLoaded = ''; $this->loadAvailableModuleFiles(); // Filters the configuration variables/file value if($this->_bot->config['modules']) { $modules = array(); $modules_to_load = helpers::toArray( $this->_bot->config['modules'] ); if($modules_to_load[0] == 'all') { // all mods removing ones starting with - $modules = $this->available_modules; // check there's more than all ie - as disabled if(count($modules_to_load) > 0){ foreach($modules_to_load as $modo){ if($modo{0} == '-'){ if(array_key_exists(substr($modo,1),$modules)){ $modulesNotLoaded .= substr($modo,1).' (skipped), '; }else{ $modulesNotLoaded .= $modo.' (not exist), '; } } } } }else{ foreach($modules_to_load as $modo){ if(array_key_exists($modo,$this->available_modules)){ $modules[$modo] = $this->available_modules[$modo]; }else{ $modulesNotLoaded .= $modo.' (no file), '; } } } ksort($modules); // Load the modules foreach($modules as $module => $mod_file) { $modulesLoaded .= $this->loadModule($module); } if($modulesLoaded) { $modulesLoaded = substr($modulesLoaded, 0, strlen($modulesLoaded)-2); $this->_bot->logger->addBotLog('Modules loaded: ' .$modulesLoaded. '.',BB_LOG_MODULE); } if($modulesNotLoaded) { $modulesNotLoaded = substr($modulesNotLoaded, 0, strlen($modulesNotLoaded)-2); $this->_bot->logger->addBotLog('Modules NOT loaded: ' .$modulesNotLoaded. '.',BB_LOG_MODULE); } } return $return; } /* * lists all modules loaded in memory */ function listLoadedModules(){ $return_string = 'Loaded modules: '; if(count($this->loaded_modules > 0)){ foreach($this->loaded_modules as $mod => $val){ $return_string .= $mod.', '; } $return_string = substr($return_string, 0, strlen($return_string)-2); } return $return_string; } /* * lists all available modules on disk */ function listAvailableModules(){ $this->loadAvailableModuleFiles(); // refresh the file list (we dont want to stop bot:-) $return_string = 'Available modules: '; foreach($this->available_modules as $mod => $foo){ $return_string .= $mod.', '; } $return_string = substr($return_string, 0, strlen($return_string)-2); $this->_bot->addLog($return_string); return $return_string; } /* * lists all modules not loaded */ function listModulesNotLoaded(){ $return_string = 'Modules not loaded: '; foreach($this->available_modules as $k => $mod){ if( !array_key_exists($k, $this->loaded_modules) ){ $return_string .= "$k, "; } } $return_string = substr($return_string, 0, strlen($return_string)-2); return $return_string; } /* * Unloades all modules in string, string is exploced and internal unloadModule() called */ function unloadModules($modules_string){ $modules = helpers::toArray($modules_string); $return_string = ''; foreach($modules as $module){ list($success, $str ) = $this->unloadModule($module); $return_string .= $str; } $return_string = trim($return_string); $return_string = 'Modules unloaded: '.substr($return_string, 0, strlen($return_string)-1); $this->_bot->logger->addBotLog($return_string, BB_LOG_MODULE); //$this->_bot->logger->addBotLog return $return_string; } /** * Unload module - internal function that removes a module * @param string $modules String containing space separated list of modulenames * @return string Descriptive strin gof action */ function unloadModule($module) { if(!array_key_exists($module, $this->available_modules)){ $str = $module . ' (doesn\'t exist), '; $success = false; }elseif(array_key_exists($module, $this->available_modules) && !isset($this->loaded_modules[$module])){ $str = $module . ' (wasn\'t loaded), '; $success = false; }elseif($this->loaded_modules[$module]->unloadable == false) { $str = $module . ' (can\'t Locked), '; $success = false; } else { unset($this->loaded_modules[$module]); $str = $module.' (unloaded), '; $success = true; } return array($success, $str); } /** * Check modules for actions on input * @param buffer $buffer * @param bambotoo $bot * @return string|None a line to log */ function check(&$buffer) { $return = ''; if($buffer->command == CTCP_VERSION) { $this->_bot->sendVersionReply($buffer->channel[0]); } if(!isset($buffer->text)) { return false; } if(strpos($buffer->text, ' ') !== false) { list($trigger, $args) = explode(' ', $buffer->text, 2); } else { $trigger = $buffer->text; $args = ''; } if(substr($trigger, 0, 1) == $this->_bot->info->usercmdchar) { $exec = USER; $trigger = substr($trigger, 1); } elseif(substr($trigger, 0, 1) == $this->_bot->info->admincmdchar) { if($this->isAdmin($buffer->userhost)) { $exec = ADMIN; $trigger = substr($trigger, 1); } else { $exec = false; } } else { $exec = 'nocmdchar'; } if($exec != false) { foreach($this->loaded_modules as $key => $module) { if($module->command == $buffer->command || $module->command == ALL) { if(($exec == $module->mode || $exec == 'nocmdchar') && (isset($module->enabled) && $module->enabled == true)) { if($module->trigger == $trigger && $exec != 'nocmdchar') { $this->loaded_modules[$key]->callModule($buffer, $this->_bot->info); $return = 'Command ' . $module->trigger . ' executed by ' . $buffer->userhost. '.'; } elseif($module->trigger == ALL) { echo "$key @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; //print_r($buffer); $this->loaded_modules[$key]->callModule($buffer, $this->_bot->info); } } } } return $return; } } /** * Check modules for timebased actions * @param bambotoo $bot */ function doEvents() { foreach($this->loaded_modules as $key => $module) { if(isset($module->event)) { $this->loaded_modules[$key]->doEventModule(); } } } /* * Updates the $available_modules array */ function loadAvailableModuleFiles(){ $this->disabled_modules = helpers::toArray( $this->_bot->config['disabled_modules']); $this->available_modules = array(); $this->getDirectory($this->modules_dir); asort($this->available_modules); } /** * Recusses into modules directories and add files to the $this->available_modules[] array * Files and directories starting with _ are ignored, module.php is stripped from name * data is stored in $available_modules where key=module_name, val = /path/to/module_file.php * @param string $dir */ function getDirectory($dir) { if(substr($dir,-1) != '/') $dir .= '/'; $dirhandle = opendir($dir); while($file = readdir($dirhandle)) { if($file != '.' && $file != '..' && is_dir($dir.$file)) { if(substr($file, 0, 1) != '_') $this->getDirectory($dir.$file); } elseif(substr($file, -10) == 'module.php' && substr($file, 0, 1) != '_') { if(!in_array(substr($file, 0, -11),$this->disabled_modules)){ $this->available_modules[substr($file, 0, -11)] = $dir.$file; } } } } /** * Check if user with this host is an admin * @param string $userhost The full IRC hostname * @return boolean */ function isAdmin($userhost) { if(isset($this->_bot->info->admins)) { foreach($this->_bot->info->admins as $admin) { if($userhost == $admin) { return true; } } } return false; } } ?>