477 lines
11 KiB
PHP
477 lines
11 KiB
PHP
|
<?php
|
||
|
/*
|
||
|
+---------------------------------------------------------------------------
|
||
|
| PHP-IRC v2.2.1 Service Release
|
||
|
| ========================================================
|
||
|
| by Manick
|
||
|
| (c) 2001-2005 by http://www.phpbots.org/
|
||
|
| Contact: manick@manekian.com
|
||
|
| irc: #manekian@irc.rizon.net
|
||
|
| ========================================
|
||
|
+---------------------------------------------------------------------------
|
||
|
| > Main module
|
||
|
| > Module written by Manick
|
||
|
| > Module Version Number: 2.2.0
|
||
|
+---------------------------------------------------------------------------
|
||
|
| > 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.
|
||
|
+---------------------------------------------------------------------------
|
||
|
| Changes
|
||
|
| =======-------
|
||
|
| > If you wish to suggest or submit an update/change to the source
|
||
|
| > code, email me at manick@manekian.com with the change, and I
|
||
|
| > will look to adding it in as soon as I can.
|
||
|
+---------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
error_reporting(E_ALL);
|
||
|
set_time_limit(0);
|
||
|
|
||
|
|
||
|
$oldDir = getcwd();
|
||
|
chdir("../scripts");
|
||
|
$__logPrefix = "lwBot";
|
||
|
$__loader = array(
|
||
|
'log', 'classloader', 'version', 'game', 'tick', 'config',
|
||
|
'db_connection', 'db_accessor', 'db', 'library'
|
||
|
);
|
||
|
require_once('loader.inc');
|
||
|
chdir($oldDir);
|
||
|
|
||
|
require('./defines.php');
|
||
|
require('./queue.php');
|
||
|
require('./module.php');
|
||
|
require('./irc.php');
|
||
|
require('./socket.php');
|
||
|
require('./timers.php');
|
||
|
require('./dcc.php');
|
||
|
require('./chat.php');
|
||
|
require('./file.php');
|
||
|
require('./parser.php');
|
||
|
require('./databases/ini.php');
|
||
|
require('./error.php');
|
||
|
require('./connection.php');
|
||
|
require('./remote.php');
|
||
|
|
||
|
|
||
|
final class bot {
|
||
|
|
||
|
/* Global socket class used by all bots */
|
||
|
private $socketClass;
|
||
|
|
||
|
/* Global process Queue used by all bots, timers, dcc classes */
|
||
|
private $procQueue;
|
||
|
|
||
|
/* Whether we are running in background mode or not. (not sure if this is used anymore */
|
||
|
private $background = 0;
|
||
|
|
||
|
//contain all the bots
|
||
|
private $bots = array();
|
||
|
|
||
|
// save the only one instance of bot (singleton)
|
||
|
private static $_instance;
|
||
|
|
||
|
public static function getInstance()
|
||
|
{
|
||
|
if (!isset (self :: $_instance))
|
||
|
{
|
||
|
self :: $_instance = new bot();
|
||
|
}
|
||
|
return self :: $_instance;
|
||
|
}
|
||
|
|
||
|
|
||
|
//Main Method
|
||
|
private function __construct()
|
||
|
{
|
||
|
|
||
|
$this->socketClass = new socket();
|
||
|
$this->procQueue = new processQueue();
|
||
|
|
||
|
$this->socketClass->setProcQueue($this->procQueue);
|
||
|
|
||
|
$this->readConfig();
|
||
|
}
|
||
|
|
||
|
public function launch(){
|
||
|
|
||
|
foreach($this->bots as $bot)
|
||
|
{
|
||
|
$this->createBot($bot);
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
|
||
|
/* Main program loop */
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
//Get data from sockets, and trigger procQueue's for new data to be read
|
||
|
$this->socketClass->handle();
|
||
|
|
||
|
//The bots main process loop. Run everything we need to!
|
||
|
$timeout = $this->procQueue->handle();
|
||
|
|
||
|
//Okay, set the socketclass timeout based on the next applicable process
|
||
|
if ($timeout !== true)
|
||
|
{
|
||
|
$this->socketClass->setTimeout($timeout);
|
||
|
}
|
||
|
|
||
|
//echo $this->procQueue->getNumQueued() . "\n";
|
||
|
//$this->procQueue->displayQueue();
|
||
|
|
||
|
//Aight, if we don't have any sockets open/in use, and
|
||
|
//we have no processes in the process queue, then there are
|
||
|
//obviously no bots running, so just exit!
|
||
|
if ($this->socketClass->getNumSockets() == 0 && $this->procQueue->getNumQueued() == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
catch (Exception $e)
|
||
|
{
|
||
|
$this->ircClass->log($e->_toString());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
public static function addBot($filename){
|
||
|
$bot = bot::getInstance();
|
||
|
$config = bot::parseConfig($filename);
|
||
|
if ($config == false)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$newBot = new botClass();
|
||
|
$newBot->config = $config;
|
||
|
$newBot->configFilename = $filename;
|
||
|
|
||
|
$bot->bots[] = $newBot;
|
||
|
$bot->createBot($newBot);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
private function createBot($bot)
|
||
|
{
|
||
|
$this->connectToDatabase($bot);
|
||
|
|
||
|
$bot->socketClass = $this->socketClass;
|
||
|
$bot->timerClass = new timers();
|
||
|
$bot->parserClass = new parser();
|
||
|
|
||
|
$bot->dccClass = new dcc();
|
||
|
$bot->ircClass = new irc();
|
||
|
|
||
|
$bot->ircClass->setConfig($bot->config, $bot->configFilename);
|
||
|
$bot->ircClass->setSocketClass($this->socketClass);
|
||
|
$bot->ircClass->setParserClass($bot->parserClass);
|
||
|
$bot->ircClass->setDccClass($bot->dccClass);
|
||
|
$bot->ircClass->setTimerClass($bot->timerClass);
|
||
|
$bot->ircClass->setProcQueue($this->procQueue);
|
||
|
|
||
|
$bot->dccClass->setSocketClass($this->socketClass);
|
||
|
$bot->dccClass->setTimerClass($bot->timerClass);
|
||
|
$bot->dccClass->setParserClass($bot->parserClass);
|
||
|
$bot->dccClass->setProcQueue($this->procQueue);
|
||
|
|
||
|
$bot->parserClass->setTimerClass($bot->timerClass);
|
||
|
$bot->parserClass->setSocketClass($this->socketClass);
|
||
|
$bot->parserClass->setDatabase($bot->db);
|
||
|
|
||
|
$bot->timerClass->setIrcClass($bot->ircClass);
|
||
|
$bot->timerClass->setSocketClass($this->socketClass);
|
||
|
$bot->timerClass->setProcQueue($this->procQueue);
|
||
|
|
||
|
$bot->parserClass->init();
|
||
|
|
||
|
//Okay, this function adds the connect timer and starts up this bot class.
|
||
|
$bot->ircClass->init();
|
||
|
|
||
|
bot::createChannelArray($bot->ircClass);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
private function readConfig()
|
||
|
{
|
||
|
global $argc, $argv;
|
||
|
|
||
|
if ($argc < 2) {
|
||
|
$args = array(config::$main['scriptdir'] . "/../ircbot/bot.conf");
|
||
|
} else {
|
||
|
$args = $argv;
|
||
|
array_shift($args);
|
||
|
}
|
||
|
|
||
|
$isPasswordEncrypt = false;
|
||
|
|
||
|
foreach ($args AS $filename)
|
||
|
{
|
||
|
if ($filename == "")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($isPasswordEncrypt == true)
|
||
|
{
|
||
|
die("Encrypted Password: " . md5($filename) . "\nReplace this as 'dccadminpass' in bot.conf!");
|
||
|
}
|
||
|
|
||
|
if ($filename == "-c")
|
||
|
{
|
||
|
$isPasswordEncrypt = true;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($filename == "-b" && $this->background != 1)
|
||
|
{
|
||
|
$this->background = 1;
|
||
|
$this->doBackground();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$config = bot::parseConfig($filename);
|
||
|
|
||
|
if ($config == false)
|
||
|
{
|
||
|
echo "Could not spawn bot $filename";
|
||
|
die();
|
||
|
}
|
||
|
|
||
|
$bot = new botClass();
|
||
|
$bot->config = $config;
|
||
|
$bot->configFilename = $filename;
|
||
|
|
||
|
$this->bots[] = $bot;
|
||
|
}
|
||
|
|
||
|
if ($isPasswordEncrypt == true) {
|
||
|
die("No password submitted on command line! Syntax: bot.php -c <new admin password>\n");
|
||
|
}
|
||
|
|
||
|
if (! $this->background && PID != '') {
|
||
|
$file = fopen(PID, "w+");
|
||
|
fwrite($file, getmypid());
|
||
|
fclose($file);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
private function connectToDatabase($bot)
|
||
|
{
|
||
|
if (isset($bot->config['usedatabase']))
|
||
|
{
|
||
|
if (!file_exists("./databases/" . $bot->config['usedatabase']. ".php"))
|
||
|
{
|
||
|
die("Couldn't find the database file! Make sure it exists!");
|
||
|
}
|
||
|
|
||
|
require_once("./databases/" . $bot->config['usedatabase']. ".php");
|
||
|
|
||
|
$dbType = $bot->config['usedatabase'];
|
||
|
|
||
|
if (!isset($bot->config['dbhost']))
|
||
|
$bot->config['dbhost'] = "localhost";
|
||
|
if (!isset($bot->config['dbuser']))
|
||
|
$bot->config['dbuser'] = "root";
|
||
|
if (!isset($bot->config['dbpass']))
|
||
|
$bot->config['dbpass'] = "";
|
||
|
if (!isset($bot->config['db']))
|
||
|
$bot->config['db'] = "test";
|
||
|
if (!isset($bot->config['dbprefix']))
|
||
|
$bot->config['dbprefix'] = "";
|
||
|
if (!isset($bot->config['dbport']))
|
||
|
{
|
||
|
$bot->db = new $dbType($bot->config['dbhost'],
|
||
|
$bot->config['db'],
|
||
|
$bot->config['dbuser'],
|
||
|
$bot->config['dbpass'],
|
||
|
$bot->config['dbprefix']);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$bot->db = new $dbType($bot->config['dbhost'],
|
||
|
$bot->config['db'],
|
||
|
$bot->config['dbuser'],
|
||
|
$bot->config['dbpass'],
|
||
|
$bot->config['dbprefix'],
|
||
|
$bot->config['dbport']);
|
||
|
}
|
||
|
|
||
|
if (!$bot->db->isConnected())
|
||
|
{
|
||
|
die("Couldn't connect to database...");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
public static function createChannelArray($ircClass)
|
||
|
{
|
||
|
$channels = $ircClass->getClientConf('channel');
|
||
|
|
||
|
if ($channels != "")
|
||
|
{
|
||
|
if (!is_array($channels))
|
||
|
{
|
||
|
$channels = array($channels);
|
||
|
}
|
||
|
|
||
|
foreach ($channels AS $channel)
|
||
|
{
|
||
|
$chan = $channel;
|
||
|
$key = "";
|
||
|
|
||
|
if (strpos($channel, chr(32)) !== false)
|
||
|
{
|
||
|
$channelVars = explode(chr(32), $channel);
|
||
|
$chan = $channelVars[0];
|
||
|
$key = $channelVars[1];
|
||
|
}
|
||
|
|
||
|
$ircClass->maintainChannel($chan, $key);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static function parseConfig($filename)
|
||
|
{
|
||
|
$configFPtr = @fopen($filename, "rt");
|
||
|
|
||
|
if ($configFPtr == null)
|
||
|
{
|
||
|
// echo "Could not find config file '".$filename."'\n";
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$configRaw = "";
|
||
|
|
||
|
try
|
||
|
{
|
||
|
|
||
|
while (!feof($configFPtr))
|
||
|
{
|
||
|
$configRaw .= fgets($configFPtr, 1024);
|
||
|
}
|
||
|
|
||
|
fclose($configFPtr);
|
||
|
|
||
|
}
|
||
|
catch (Exception $e)
|
||
|
{
|
||
|
// echo "A fatal IO Exception occured.";
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$config = array();
|
||
|
|
||
|
$configRaw = str_replace("\r", "", $configRaw);
|
||
|
|
||
|
$confLines = explode("\n", $configRaw);
|
||
|
|
||
|
foreach ($confLines AS $line)
|
||
|
{
|
||
|
$line = trim($line);
|
||
|
|
||
|
if ($line == "" || substr($line, 0, 1) == ";")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$offsetA = strpos($line, chr(32));
|
||
|
|
||
|
if ($offsetA != false)
|
||
|
{
|
||
|
$confVar = substr($line, 0, $offsetA);
|
||
|
$confParams = substr($line, $offsetA + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$confVar = $line;
|
||
|
$confParams = "";
|
||
|
}
|
||
|
|
||
|
if (preg_match('/__CFG:([a-zA-Z_]+)__/', $confParams, $matches)) {
|
||
|
$src = array(); $dst = array();
|
||
|
array_shift($matches);
|
||
|
foreach ($matches as $cfgSubst) {
|
||
|
array_push($src, "/__CFG:{$cfgSubst}__/");
|
||
|
array_push($dst, config::$main[$cfgSubst]);
|
||
|
}
|
||
|
$confParams = preg_replace($src, $dst, $confParams);
|
||
|
}
|
||
|
|
||
|
if (isset($config[$confVar]))
|
||
|
{
|
||
|
if (!is_array($config[$confVar]))
|
||
|
{
|
||
|
$prevParam = $config[$confVar];
|
||
|
$config[$confVar] = array();
|
||
|
$config[$confVar][] = $prevParam;
|
||
|
}
|
||
|
|
||
|
$config[$confVar][] = $confParams;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$config[$confVar] = $confParams;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $config;
|
||
|
}
|
||
|
|
||
|
|
||
|
private function doBackground()
|
||
|
{
|
||
|
$pid = pcntl_fork();
|
||
|
if ($pid == -1) {
|
||
|
die("Error: could not fork\n");
|
||
|
} else if ($pid) {
|
||
|
if (PID != "") {
|
||
|
$file = fopen(PID, "w+");
|
||
|
fwrite($file, $pid);
|
||
|
fclose($file);
|
||
|
}
|
||
|
|
||
|
exit(); // Parent
|
||
|
}
|
||
|
|
||
|
if (!posix_setsid()) {
|
||
|
die("Error: Could not detach from terminal\n");
|
||
|
}
|
||
|
|
||
|
fclose(STDIN);
|
||
|
fclose(STDOUT);
|
||
|
fclose(STDERR);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
$ircBot = bot::getInstance();
|
||
|
$ircBot->launch();
|
||
|
|
||
|
?>
|