<?php

/*
Manu-Admin-Mod v0.11.5 beta - Administration tool for CoD4 gameservers
Copyright (C) 2008-2010  Manuel Kress

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 3 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, see <http://www.gnu.org/licenses/>.
*/

error_reporting(E_ALL);
define("STARTUPTIME", time());

if (PHP_SAPI != "cli") {
    die ("<h1>This program cannot be run on a webspace!</h1>");
}

//See http://www.php.net/manual/de/timezones.php if you have to change this
//When $mod->readConfig(); is done, this will be set to the value set in config.cfg
date_default_timezone_set("Europe/Berlin");

define("VERSION", "0.11.5 Beta");
$version = VERSION;

echo <<<LIZENZ
Manu-Admin-Mod v{$version}  Copyright (C) 2008-2010  Manuel Kress
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions.
Visit http://manuadminmod.de if you have any trouble


LIZENZ;

//Load functions
require_once ("internals/functions.php");

//Read command line arguments
try {
    $args = parse_argv(
        array(
            "force" => array("count" => 2, "multiple" => true),
            "configdir" => array("count" => 1, "multiple" => false),
            "logdir" => array("count" => 1, "multiple" => false),
            "splitlog" => array("count" => 1, "multiple" => false),
            "usemysql" => array("count" => 5, "multiple" => false),
            "adminfile" => array("count" => 1, "multiple" => false),
            "configfile" => array("count" => 1, "multiple" => false),
            "groupsfile" => array("count" => 1, "multiple" => false),
            "mapsfile" => array("count" => 1, "multiple" => false),
            "reasonsfile" => array("count" => 1, "multiple" => false),
        )
    );
}
catch (Exception $e) {
    die("Error in command line parameters: " . $e->getMessage());
}


//Log and Config Dir
if (!isset($args["configdir"])) {
	$configdir = "config";
}
else {
	$configdir = $args["configdir"];
}
if (!isset($args["logdir"])) {
	$logdir = "log";
}
else {
	$logdir = $args["logdir"];
}


if (isset($args["configfile"])) {
	$mod->setConfigFileName("config", $args["configfile"]);
}
if (isset($args["groupsfile"])) {
	$mod->setConfigFileName("groups", $args["groupsfile"]);
}
if (isset($args["mapsfile"])) {
	$mod->setConfigFileName("maps", $args["mapsfile"]);
}
if (isset($args["reasonsfile"])) {
	$mod->setConfigFileName("reasons", $args["reasonsfile"]);
}
if (isset($args["adminfile"])) {
	$mod->setConfigFileName("admins", $args["adminfile"]);
}

define("LOGDIR", $logdir);



//Logprefix

$splitlog = isset($args["splitlog"]) ? strtolower($args["splitlog"]) : "no";
switch ($splitlog) {
    case 'no':
        $filename = 'mod.log';
        break;
    case 'datetime':
        $filename = "mod_" . date('d-m-y_h-i-s') . ".log";
        break;
    case 'unix':
        $filename = "mod_" . time() . ".log";
        break;
    default:
        if (is_numeric($splitlog)) {
            $filename = "mod.log";
            if (filesize (LOGDIR . "/" . $filename) > ($splitlog * 1024 * 1024)) {
                $fp = fopen(LOGDIR . "/" . $filename, "r");
                fseek($fp, 12, SEEK_SET);
                $timestamp = fread($fp, 17);
                $timestamp = str_replace(array(".", ":", " "), array("-", "-", "_"), $timestamp);
                fclose($fp);
                rename(LOGDIR . "/" . $filename, LOGDIR . "/mod_$timestamp.log");
            }
        }
        else {
            die("Unrecognized value for parameter -splitlog: '$splitlog'");
        }
}

ini_set("log_errors", "1");
ini_set("error_log", LOGDIR."/$filename");
$logging = new log(LOGDIR . "/$filename");
set_error_handler("error_handler");

$logging->write(MOD_NOTICE, "==========================================");
$logging->write(MOD_NOTICE, "Manu-Admin-Mod v{$version} is starting...");
$logging->write(MOD_NOTICE, "==========================================");
$logging->write(MOD_NOTICE, "  !! Please wait until the mod is completely initialised");

//declare mod object
if (isset($args["usemysql"])) {
    $mod = new mod_mysql($args["usemysql"][0], $args["usemysql"][1], $args["usemysql"][2], $args["usemysql"][3], $args["usemysql"][4]);
}
else {
    $mod = new mod;
}

//set default CVs (ConfigVars)
require "internals/defaultcfg.php";

if (!$mod->setConfigDir($configdir)) {
	$logging->write(MOD_ERROR, "Couldn't find config dir: $configdir");
}


//Forced ConfigVars
if (!empty($args["force"])) {
    foreach ($args["force"] as $configvar) {
        if (!preg_match('|^\[([a-z0-9_]+)\]([a-z0-9_]+)$|i', $configvar[0], $subpatterns)) {
            $logging->write(MOD_WARNING, "Syntax error detected while trying to force ConfigVar '$configvar[0]'");
            continue;
        }
        $mod->forceConfigVar($subpatterns[1], $subpatterns[2], $configvar[1]);
    }
}

//Read config
$mod->readConfig();

//open rcon connection
try {
    if ($mod->getCV("main", "logrcon")) {
        $rcon = new q3query_log($mod->getCV("main", "ip"), $mod->getCV("main", "port"), LOGDIR . "/rcon.log");
    }
    else {
        $rcon = new q3query($mod->getCV("main", "ip"), $mod->getCV("main", "port"));
    }


    $rcon->setRconpassword($mod->getCV("main", "rconpassword"));

    //test rcon connection
    $return = $rcon->rcon("version");
    if (stripos($return, "Invalid password") !== false) {
    	throw new Exception("RCON connection failed: Wrong RCON password");
    }
    elseif (stripos($return, "The server must set 'rcon_password'")) {
        throw new Exception("RCON connection failed: There is no rcon password set on the server. Please set a rcon password in your server.cfg (set rcon_password PASSWORD)");
    }
    elseif (empty($return)) {
        throw new Exception("RCON connection not valid, check wether your config (IP + port) is correct and your gameserver is running");
    }
}

catch (Exception $e) {
    $logging->write(MOD_ERROR, $e->getMessage());
}
$logging->write(MOD_NOTICE, "RCON connection established (".$mod->getCV("main", "ip") . ":" . $mod->getCV("main", "port"). ")");


//Detect Game
$game = $mod->rconGetDvar("gamename");
if ($game == "Call of Duty 4") {
    $mod->setGame("cod4");
}
elseif ($game == "Call of Duty: World at War") {
    $mod->setGame("cod5");
}
elseif ($game == "Call of Duty 2") {
    $mod->setGame("cod2");
}
elseif ($game == "IW4") {
    $mod->setGame("cod6");
    $game = "Call of Duty - Modern Warfare 2 (alterIWnet)";
}
else {
    $logging->write(MOD_ERROR, "Unknown game detected: $game");
}

$logging->write(MOD_NOTICE, "Game detected: $game");

//test required Dvars
if ($mod->getGame() == "cod2") {
    $logging->write(MOD_WARNING, "Dvars can't be checked when game is CoD2, skipping check");
    $logging->write(MOD_WARNING, "Please manually check this Dvars: g_logsync >= 1; sv_log_damage = 1; logfile = 1");
    $logging->write(MOD_WARNING, "This msg does NOT mean that the Dvars are actually wrong, but they CAN be");
}
else {
    $test = $mod->rconDvarList("*_log");
    if ($test["g_logsync"] < 1) {
        $logging->write(MOD_ERROR, "Dvar 'g_logsync' must be greater or equal to 1, current: $test[g_logsync]");
    }
    elseif ($test["sv_log_damage"] != 1) {
        $logging->write(MOD_ERROR, "Dvar 'sv_log_damage' must be qual to 1, current: $test[sv_log_damage]");
    }
    else {
        $logging->write(MOD_NOTICE, "Dvar check successful");
    }
}

//players
$players = array();

//Get playerlist and map from status
$mod->syncPlayerlist(true);
//Get gametype
$mod->updateGametype();
//Get Teamnames
$mod->updateTeamNames();
//Set Version info to gameservers status
$mod->setVersionDvar();

$logging->write(MOD_NOTICE, "== Loading plugins and commands ==");

//include plugin files
$dir = opendir("plugins");
while (($file = readdir($dir)) !== false) {
	if (in_array($file, array(".", ".."))) continue;
	if (substr($file, -4, 4) == ".php") {
	    $logging->write(MOD_NOTICE, " - Loading $file");
	    include("plugins/" . $file);
	}
}
closedir($dir);

$logging->write(MOD_NOTICE, "== Finished loading plugins ==");

//Announce startup
$mod->rconSay($mod->getLngString("watchingServer"));

//initialisation finished
$logging->write(MOD_NOTICE, "  !! Finished initialisation");


//Now start parsing the log files

//declare $parser object;
if (!$mod->getCV("ftp", "enabled")) {
    $parser = new parser($mod->getCV("main", "logfile"), $success);
}
else {
    $parser = new parser_ftp($mod->getCV("main", "logfile"), $success, $mod->getCV("ftp", "host"), $mod->getCV("ftp", "user"), $mod->getCV("ftp", "password"), $mod->getCV("ftp", "port"), (bool)(int)$mod->getCV("ftp", "passive"));
}
if (!$success) {
	$logging->write(MOD_ERROR, "Couldn't open server's logfile: '".$mod->getCV("main", "logfile")."'");
}

$logging->write(MOD_NOTICE, "=== Start processing loglines... ===");


if (count($players) <= 6 || $mod->getCV("main", "antistartupbug") == "0") {
    $waitOnNextMap = false;
}
else {
    $waitOnNextMap = true;
    $players = array();
}
$mapRestartPerformed = false;

while (true) {

    clearstatcache();

	$newlines = $parser->getNewLines();

	foreach ($newlines as $line) {
		$line = $parser->parseLine($line);
		if (!$line) continue;

		if ($parser->getTimeStampType() == "absolute") {
		    $uptime = $parser->getLastParsedTimeStamp();
		}
		else {
		    $timestamp = $parser->getLastParsedTimeStamp();
		    $seconds = $timestamp % 60;
		    $minutes = ($timestamp - $seconds) / 60;
		    $uptime = "$minutes:" . str_pad($seconds, 2, "0", STR_PAD_LEFT);

		}
		log::setUptime($uptime);

		if ($waitOnNextMap) {
		    if ($line["action"] != "nextmap") {
		        if ($mod->getCV("main", "antistartupbug") == "restart" && !$mapRestartPerformed) {
		            $mod->rconMapRestart(true);
		            $mapRestartPerformed = true;
		        }
		        continue;
		    }
		    else {
		        $waitOnNextMap = false;
		    }
		}

		$mod->triggerEvent("logAction", $line);

		switch ($line["action"]) {
			case "damage":
                $mod->actionDamage($line["parsed"]);
				break;

			case "vehicledamage":
			    //Damage given to Tanks
                $mod->actionVehicleDamage($line["parsed"]);
				break;

			case "actorsdamage":
			    //Damage given to Dogs!
                $mod->actionActorsDamage($line["parsed"]);
				break;

			case "kill":
                $mod->actionKill($line["parsed"]);
				break;

			case "join":
				$mod->actionJoin($line["parsed"]);
				break;

			case "jointeam":
			    $mod->actionJoinTeam($line["parsed"]);
			    break;

			case "quit":
				$mod->actionQuit($line["parsed"]);
				break;

			case "say":
			case "sayteam":
				$mod->actionSay($line["parsed"]);
				break;

			case "nextmap":
				$mod->actionNextMap($line["parsed"]);
				break;

			case "tie":
			case "win":
			case "loss":
			    $mod->actionResult($line["action"], $line["parsed"]);
                break;

			case "bombplanted":
			case "bombdefused":
			case "flagcaptured":
			case "flagtaken":
			case "flagreturned":
			case "hqcaptures":
			case "hqdestroyed":
			    $mod->actionAction($line["action"], $line["parsed"]);
                break;

			case "action":
			    $mod->actionActionCoD2($line["parsed"]);
                break;

			case "mapend":
				break;

			default: continue; //Empty lines e.g.
		}

	}

	$mod->triggerEvent("everyTime");

	if ($parser instanceof parser_ftp ) {
	    sleep(1);
	}
	else {
	    usleep(100000);
	}
}



?>