Sprache: EN FR PT ES NL DE SV RU
<?php

 
declare(ticks = 1);
if (! function_exists('pcntl_fork')) die('PCNTL functions not available on this PHP installation');
echo "Start of program!\n";
if (isset($argv[1])) {
    if ($argv[1] == 'verbose' || $argv[1] == '-v') {
        $verbose = 1;
    } elseif ($argv[1] == 'vv' || $argv[1] == '-vv') {
        $verbose = 2;
    } else {
        $verbose = 0;
    }
} else {
    $verbose = 0;
}


require_once("/home/pugbot/tracker/q3query.php");
require_once("/home/pugbot/tracker/align.php");
include("/home/pugbot/tracker/dbconfig.php");

// connect to db

function mcrypt($data) {
    $key = 'ASsadfEYHr345REtrte74hHFGDsret7245dFDGDFer3D7hhs4467H85p';
    $iv = '82952684';
    $todec = base64_decode($data);
    $decrypted = mcrypt_decrypt( MCRYPT_BLOWFISH, $key, $todec, MCRYPT_MODE_CBC, $iv );
    return $decrypted;
}

function send_rcon($command, $server_host, $server_port, $rcon_pass) {
    
    if ($server_host == "" || !isset($server_host)) {
        return FALSE;
    }
    
    // Set server, port and RCON for server to be used.
    $q = new q3query($server_host, $server_port);
    $q->set_rconpassword($rcon_pass);

    // Make sure variables are clean.
    $failed = 0;
    $rconresponse = 0;
    while ($failed != 8 && !($rconresponse)) {
        $q->rcon($command);
        $rconresponse = $q->get_response();
        //echo $rconresponse;
        $failed++;
        if (!($rconresponse)) { sleep(1); }
    }
    if ($failed == 8) {
        return FALSE;
    } else {
        return $rconresponse;
    }
}

function sig_handler($signo) {
    if($signo == SIGUSR1) {
        // Handle SIGUSR1
        echo "SIG: ".$signo."\n";
    } elseif($signo == SIGTERM) {
        // Handle SIGTERM
        echo "SIG: ".$signo."\n";
        $sigterm = true;
    } elseif($signo == SIGHUP) {
        // Handle SIGHUP
        echo "SIG: ".$signo."\n";
        $sighup = true;
    }
}

// Function for thread to track each server
function track_server($server_to, $pid, $verbose) {
    
    // Setup the align class for thread
    $align = new align($verbose);

    // Include DB info
    include("/home/pugbot/tracker/dbconfig.php");
    
    //$align->align_d_echo_a($db);
    
    // Make the database connection for this thread.
    $server_connection = mysql_connect($db['host'], $db['user'], $db['pass'], TRUE) or die ("Unable to connect!");
    mysql_select_db($db['db']) or die ("Unable to select database!");
    
    startserver:
    // setup the vars
    $server_id     = $server_to;
    $server_query  = mysql_query("SELECT * FROM `servers` WHERE `server_id`='$server_id' AND `status`!='RCONFAIL'") or die("unable to query table! track_server, line: 84 ".$server_id);
    $server        = mysql_fetch_array($server_query);

    $align->align_s_echo_a(array("SERVER_ID"=>$server_id,"TRACKING!"=>"STARTED!"));    
    
    if (!$server) {
        $align->align_s_echo_a(array("SERVER_ID"=>$server_id,"RCON!"=>"FAILED!"));    
    } else {
    
    $server_host   = gethostbyname($server['host']);
    $server_port   = $server['port'];
    $rcon_pass_enc = $server['rcon'];
    $rcon_pass     = mcrypt($rcon_pass_enc);
    $rcon_pass     = trim($rcon_pass,"\0");
    $thread_name   = "Thread for server ID ".$server_id;
    
    // Set the process title (shows up in "ps aux")
    setproctitle($thread_name);
    
    // Infinite tracking loop, never stop, at least try not to.
    while (TRUE) {
        
        // Like to sleep a lot with urt rcon commands to help prevent rcon flood conditions.
        sleep(1);

        // Set the pid in the servers table
        mysql_query("UPDATE `servers` SET `tracker_pid`=0 WHERE `server_id`='$server_id' ");
        
        // Echo to console some basic status information.
        $align->align_d_echo_a(array("SERVER_ID"=>$server_id,"UPDATING!"=>"STARTED!"));
        
        // Set the time for this pass on tracking
        $start_time = time();
        
        // fetch connected players via rcon
        $command         = "status";
        $status_response = send_rcon($command, $server_host, $server_port, $rcon_pass);
        
        /* If statements for checking $status_response */
        if (isset($status_response)) {
            if ($status_response === FALSE || $status_response == FALSE) {
                mysql_query("UPDATE `servers` SET `status`=\"RCONFAIL\" WHERE `server_id`='$server_id' ");
                // Some debug output
                $align->align_s_echo_a(array("SERVER_ID"=>$server_id,"STATUS!"=>"FAILED!"));
                goto startserver;
            } else {
                // Some debug output
                $align->align_s_echo_a(array("SERVER_ID"=>$server_id,"STATUS!"=>"SUCCEEDED!"));
                //echo $status_response;
            }
        } else {
            // Some debug output
            $align->align_s_echo_a(array("SERVER_ID"=>$server_id,"STATUS!"=>"FAILED!"));
            goto startserver;
        }
            
        // Like to sleep a lot with urt rcon commands to help prevent rcon flood conditions.
        sleep(1);
        
        // Some magic TheRick found/came up with.
        preg_match_all('/^\s+(\S{1,2}?)\s+(\S{1,4})\s+(\S{1,3})\s+(.*)\^7\s+(\S+)\s+(\S+):(\S+)\s+(\S+)\s+(\S+)$/m', $status_response,$type);
        preg_match('/^map:\s+(.*)$/m', $status_response, $aMap);
        
        // This line sets the map on the server from the rcon status
        if (isset($aMap[1])) {
            $map = $aMap[1];
            mysql_query(" UPDATE `servers` SET `current_map`='$map' WHERE `server_id`='$server_id' ");
        } else {
            $align->align_v_echo_a($aMap);
            $align->align_v_echo_a(array("SERVER_ID"=>$server_id,"STATUS"=>$status_response));
        }

        // Setup rcon to grab sv_hostname
        $command = "sv_hostname";
        
        // Send sv_hostname command
        $sv_hostname_response = send_rcon($command, $server_host, $server_port, $rcon_pass);
        
        sleep(1);
        
        $sv_first_split = split("is:\"", $sv_hostname_response);
        if (isset($sv_first_split[1])) { 
            $sv_second_split = split("\^7\" default:",$sv_first_split[1]);
            $sv_hostname = mysql_real_escape_string($sv_second_split[0]);
            $align->align_v_echo_a(array("SERVER_ID"=>$server_id,"sv_hostname"=>$sv_hostname_response));
        } else {
            $align->align_v_echo_a(array("SERVER_ID"=>$server_id,"sv_hostname"=>$sv_hostname_response));
            $sv_hostname = "Bad server name query";
            // Set num players and sv_hostname in servers database
            mysql_query("UPDATE `servers` SET `name`='$sv_hostname' WHERE `server_id`='$server_id'");
            goto startserver;
        }
                
        // Setup rcon to grab sv_hostname
        $command = "g_gametype";
        
        // Send sv_hostname command
        $gametype_response = send_rcon($command, $server_host, $server_port, $rcon_pass);
        
        sleep(1);
        
        $gametype_first_split = split("is:\"", $gametype_response);
        if (isset($gametype_first_split[1])) {
            $gametype_second_split = split("\^7",$gametype_first_split[1]);
            $gametype = $gametype_second_split[0];
        } else {
            $align->align_v_echo_a(array("SERVER_ID"=>$server_id,"g_gametype"=>$gametype_response));
            $gametype = 0;
            // Set num players and sv_hostname in servers database
            mysql_query("UPDATE `servers` SET `gametype`='$gametype' WHERE `server_id`='$server_id'");
            goto startserver;
        }
            
        // Clear the user records from temp table
        mysql_query( "DELETE FROM `tracker_active` WHERE `server_id`='$server_id'" );
            
        // Count the number of players in server, by counting the number of pids
        $count = count($type[1]);
        
        // Loop for each player found
        for( $i=1; $i<=$count ;$i++ ) {
                
            // Player slots start at zero, but loop starts at 1, subtract 1.
            $num     = $i-1;
                
            // Player pid
            $pid     = $type[1][$num];
                
            // Player score
            $score   = $type[2][$num];
                
            // Player ping
            $ping    = $type[3][$num];
                
            // Player name, must be mysql escaped as a name could actually be an injection point
            $name    = mysql_real_escape_string($type[4][$num]);
                
            // Lastmsg
            $lastmsg = $type[5][$num];
                
            // Player's IP
            $ip      = $type[6][$num];
                
            // Players net_port
            $port    = $type[7][$num];
                
            // Players qport
            $qport   = $type[8][$num];
                
            // Players connected rate
            $rate    = $type[9][$num];

            // split up the IP into 4 parts (octets)
            $ip_array = explode(".",$ip);
            $ip1 = $ip_array[0];
            $ip2 = $ip_array[1];
            $ip3 = $ip_array[2];
            $ip4 = $ip_array[3];

            // get the ipkey of IP
            $ipkey = (($ip1*256+$ip2)*256+$ip3)*256 + $ip4;
            $truename = stripslashes($name);
            // Setup the rcon dumpuser for this pid
            $command = "dumpuser \"".$truename."\"";
                
            // Send dumpuser rcon command
            $dump_response = send_rcon($command, $server_host, $server_port, $rcon_pass);
                
            // Sleep some more after rcon command
            sleep(1);
                
            // Set guid blank to make sure there isn't a left over in memory
            $guid = "";
            
            // Do the same for sacc_maxpackets
            $sacc_maxpackets = 0;
            
            // Split the rcon response from the dumpuser command
            $peices = preg_split("/[\s,]+/", $dump_response, -1, PREG_SPLIT_NO_EMPTY);

            // Foreach piece in $pieces, run this loop, which gets guid and sacc_maxpackets from dumpuser
            foreach ($peices as $key=>$piece) {
                
                // If the piece == guid then set the guid
                if ($piece == "cl_guid") {
                
                    // Make sure to escape the guid, adding +1 to the key to get the value
                    $guid = mysql_real_escape_string($peices[($key + 1)]);
                
                    // Some debug output
                    //echo $align->left("SERVER_ID", 10).": ".$align->left($server_id, 7).$align->left("NAME",15).": ".$align->left($name, 0).$align->left("GUID FOUND", 0).": ".$guid."\n";
                }
            
                // If the piece == sacc_maxpackets then set the variable
                if ($piece == "sacc_maxpackets") {
            
                    // Set maxpackets, adding +1 to the key to get the value
                    $sacc_maxpackets = $peices[($key + 1)];
                
                    // Some debug output
                    $align->align_s_echo_a(array("SERVER_ID"=>$server_id,"SACC FOUND"=>$name));
                }
            }
            
            if (!strpos($dump_response,"is not on the") && $guid != "") {
                    // If the IP != the ip of the GTV bot then add to the database
                if ($ip != "208.93.223.133") {
                
                    // Some debug output
                    $align->align_d_echo_a(array("SERVER_ID"=>$server_id,"NAME"=>$name,"ADDING IP TO DB"=>$ip));
                
                    // Make the mysql query to add the player to the database
                    mysql_query(" INSERT INTO `ircpug`.`tracker_active` (`key`, `server_id`, `pid`, `score`, `ping`, `name`, `lastmsg`, `ip`,`ipkey`, `port`, `qport`, `rate`, `GUID`, `sacc_maxpackets`) VALUES (NULL, '$server_id', '$pid', '$score', '$ping', '$name', '$lastmsg', '$ip','$ipkey', '$port', '$qport', '$rate', '$guid', '$sacc_maxpackets'); ");
                
                } else {
                
                    // Some debug output
                    $align->align_d_echo_a(array("SERVER_ID"=>$server_id,"NAME"=>$name,"*NOT ADDING IP TO DB"=>$ip));
                }
            } elseif ($guid == "") { 
                if (!isset($sacc)) { $sacc = 0; }
                $align->align_v_echo_a(array("SERVER_ID"=>$server_id,"NAME"=>$name,"SACC"=>$sacc,"SLOT"=>$pid,"GUID BLANK"=>$dump_response));
            } else { 
                if (!isset($sacc)) { $sacc = 0; }
                $align->align_v_echo_a(array("SERVER_ID"=>$server_id,"NAME"=>$name,"SACC"=>$sacc,"SLOT"=>$pid,"GUID NOT"=>$dump_response));
            }
        }
            
        // Select all the players we just added to the temp database table for this server
        $update_players = mysql_query("SELECT * FROM `tracker_active` WHERE `server_id`='$server_id'");
    
        // Get num players in server
        $server_num_players = mysql_num_rows($update_players);
    
        // Set num players and sv_hostname in servers database
        mysql_query("UPDATE `servers` SET `gametype`='$gametype',`name`='$sv_hostname',`players`='$server_num_players' WHERE `server_id`='$server_id'");
    
        // If the query failed, output some debug info, else query successful update the new temp table
        if (!$update_players) {
        
            // Output some debug info
            $align->align_s_echo("FAILED SERVER_ID",$server_id);
        
        } else {
        
            // Delete all players from the second temp table for this server
            mysql_query( "DELETE FROM `tracker_status` WHERE `server_id`='$server_id'" );
        
            // Run this loop for each player, inserting them into the second temp table
            while ($player_info = mysql_fetch_array($update_players)) {
            
                //$align->align_d_echo_a($player_info);
                // Set the variables to be set in the second temp table
                $name            = mysql_real_escape_string($player_info['name']);
                $server_id       = $player_info['server_id'];
                $pid             = $player_info['pid'];
                $score           = $player_info['score'];
                $ping            = $player_info['ping'];
                $lastmsg         = $player_info['lastmsg'];
                $ip              = $player_info['ip'];
                $ipkey           = $player_info['ipkey'];
                $port            = $player_info['port'];
                $qport           = $player_info['qport'];
                $rate            = $player_info['rate'];
                $guid            = mysql_real_escape_string($player_info['GUID']);
                $sacc_maxpackets = $player_info['sacc_maxpackets'];
            
                // Add the player to the second temp table here, second temp table gets handled by main thread from here
                mysql_query(" INSERT INTO `ircpug`.`tracker_status` (`key`, `server_id`, `pid`, `score`, `ping`, `name`, `lastmsg`, `ip`,`ipkey`, `port`, `qport`, `rate`, `GUID`, `sacc_maxpackets`) VALUES (NULL, '$server_id', '$pid', '$score', '$ping', '$name', '$lastmsg', '$ip','$ipkey', '$port', '$qport', '$rate', '$guid', '$sacc_maxpackets'); ");
            }
        }
    
        // Count how long it took to track all players on server
        $total_time = time() - $start_time;
    
        // Some debug output
        $align->align_d_echo_a(array("SERVER_ID"=>$server_id,"DONE UPDATING!"=>"TOOK:","TIME"=>$total_time));
    }
    }
}

function keep_tracking($verbose) {
    include("/home/pugbot/tracker/dbconfig.php");
    $align = new align($verbose);
    while (TRUE) {
        $start_time = time();

        $align->align_s_echo("STARTING SERVERS!",$start_time);
        
        $connection = mysql_connect($db['host'], $db['user'], $db['pass'], TRUE) or die ("Unable to connect!");
        mysql_select_db($db['db']) or die ("Unable to select database! keep_tracking".$db['db']);
        
        // grab players in servers
        $status_q = mysql_query(" SELECT * FROM `tracker_status` ");
        
        // Get all servers and try to check on the pid
        $servers_q = mysql_query(" SELECT * FROM `servers` WHERE `status`!='RCONFAIL'");
        
        // For each server get pid n check
        while ($server = mysql_fetch_array($servers_q)) {
            
            // Set the $pid
            $pid_count = $server['tracker_pid'];
            
            // Set server_id
            $server_id = $server['server_id'];
            
            if ($pid_count > 20) {
                
                $pid = pcntl_fork();
                if ($pid == 0) {
                    $align->align_s_echo("Forked child",$pid);
                } elseif ($pid == -1) {
                    $align->align_s_echo("Failed to fork!",$pid);
                } else {
                    $align->align_s_echo("Child started!",$pid);
                    track_server($server_id, $pid, $verbose);
                exit(35);
                }
                $pid_count = 0;
            } else {
                // add +1 to the pid
                $pid_count++;
            }
            
            // update the pid in the servers table
            mysql_query("UPDATE `servers` SET `tracker_pid`='$pid_count' WHERE `server_id`='$server_id'");

            // Output some debug info
            $align->align_s_echo("TRACKER CHECKING!",$server_id);
            //$align->align_d_echo_a(array("SERVER_ID"=>$server_id,"TRACKER CHECKING!"=>"COMPLETE!"));
        }

        // start timer
        $timer_start_urtplayers = time();

        // for each player, do the following
        while ($status = mysql_fetch_array($status_q)) {
            // setup the vars
            $name            = mysql_real_escape_string($status['name']);
            $server_id       = $status['server_id'];
            $pid             = $status['pid'];
            $score           = $status['score'];
            $ping            = $status['ping'];
            $lastmsg         = $status['lastmsg'];
            $ip              = $status['ip'];
            $ipkey           = $status['ipkey'];
            $port            = $status['port'];
            $qport           = $status['qport'];
            $rate            = $status['rate'];
            $guid            = mysql_real_escape_string($status['GUID']);
            $sacc_maxpackets = $status['sacc_maxpackets'];
            $ip_search       = mysql_query(" SELECT `tuser_id` FROM `tracker_aliases` WHERE `ip`='$ip'  AND `alias`='$name' AND `GUID`='$guid' AND `server_id`='$server_id'");
            $user_array      = mysql_fetch_array($ip_search);
            $tuser           = $user_array[0];
            $rows            = mysql_num_rows($ip_search);
            $align->align_d_echo_a(array("SERVER_ID"=>$server_id,"TRACKER UPDATING!"=>"STARTING!"));
            
            // if it matches then do this stuff
            if ($rows != 0) {
                // check if alias has been on this IP before
                $alias_check = mysql_query(" SELECT * FROM `tracker_aliases` WHERE `alias`='$name' AND `ip`='$ip' AND `GUID`='$guid' AND `server_id`='$server_id'");

                // if it has then update the counter
                $rows = mysql_num_rows($alias_check);
                if ($rows > 0) {
                    mysql_query(" UPDATE `tracker_aliases` SET `counter`=`counter`+1 , `last_time`='$start_time' WHERE `tuser_id`='$tuser' ");
                } elseif ($rows == 0 && $guid != "") {
                    mysql_query(" INSERT INTO `tracker_aliases`(`alias`,`ipkey`,`counter`,`ip`,`GUID`,`sacc_maxpackets`,`server_id`,`first_time`) VALUES('$name','$ipkey','0','$ip','$guid','$sacc_maxpackets','$server_id','$start_time') ");
                }
            } elseif ($rows == 0) {
                mysql_query(" INSERT INTO `tracker_aliases`(`alias`,`ipkey`,`counter`,`ip`,`GUID`,`sacc_maxpackets`,`server_id`,`first_time`) VALUES('$name','$ipkey','0','$ip','$guid','$sacc_maxpackets','$server_id','$start_time') ");
            }
        }
        $total_time = time() - $start_time;
        $align->align_d_echo_a(array("SERVER_ID"=>$server_id,"TRACKER UPDATING!"=>"STARTING!","TIME"=>$total_time));
        sleep(5);
        mysql_close($connection);
    }
}


pcntl_signal(SIGUSR1, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");

//$connection = mysql_connect($db['host'], $db['user'], $db['pass']) or die ("Unable to connect!");
//mysql_select_db($db['db']) or die ("Unable to select database!");

/*
// grab server information
$server_q = mysql_query(" SELECT * FROM `servers` WHERE `status`<>'badpass' ");

$server_id = array();
// for each server, do the following
while ($server = mysql_fetch_array($server_q)) {
    $server_id[] = $server['server_id'];
}
mysql_close($connection);
*/
/* foreach ($server_id as $server_to) {
    $pid = pcntl_fork();

    if ($pid == 0) {
        echo "Forked child #{$pid}\n\n";
    } elseif ($pid == -1) {
        echo "Failed to fork! #{$pid}\n\n";
    } else {
        echo "Child! {$pid} =====================================================\n";
        track_server($server_to, $pid);
           exit(35);
    }
    
} */
setproctitle  ( "Slacks multithreaded tracker"  );
keep_tracking($verbose);

print "Done! :^) PID: {$pid} \n\n";
?>