Advertisement
Vearie

BZ2 Master Server 2.0 PHP Script

Feb 3rd, 2015
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 8.29 KB | None | 0 0
  1. <?php
  2.     $BZ2_SERVER_VERSION = "v2.0";
  3.     # ------------:
  4.     # REQUIREMENTS:
  5.     # MySQL database.
  6.     # PHP with MySQLi http://php.net/manual/en/mysqli.requirements.php
  7.     # PHP Version 5.2.0 (For JSON.)
  8.     # ------------:
  9.     # INSTALLATION:
  10.     # 1. Put testSever.php into your site's root directory.
  11.     # Mind the case sensitivity on linux servers.
  12.     # 2. Set up your MySQL database for BZ2 usage. See "BZ2MySQL_Setup.txt" or http://pastebin.com/Fqry3dMN.
  13.     $sqlPort = 3306; $sqlHost = "127.0.0.1";
  14.     $sqlUsername = "BZ2MGR"; $sqlPassword = "asdf123";
  15.     $sqlDatabase = "bz2_gamelist";
  16.     # 3. Set the string variable below to your hostname.
  17.     $siteHostName = "localhost";
  18.     # -------------:
  19.     # CONFIGURATION:
  20.     $cfgUseGsoff = TRUE;                         # Allow users to hide their games via ?gsoff=1.
  21.     $cfgMultTimeout = 1.3;                       # Multiply timeout time, 1.0 = 100% (no change).
  22.     $cfgFakeLobbyName = "http://www.bz2maps.us"; # Set to NULL to disable this feature.
  23.     # -------------------------------------------------------------------
  24.    
  25.     # Important Global Variables
  26.     $serverOutput = "";
  27.     $IP = $_SERVER["REMOTE_ADDR"];
  28.     $reqMethod = $_SERVER["REQUEST_METHOD"];
  29.    
  30.     # Initialize MySQL
  31.     $SQLiDatabase = new mysqli($sqlHost, $sqlUsername, $sqlPassword, $sqlDatabase, $sqlPort) or die("Failed to connect to MySQL server.");
  32.     $SQLiDatabase->set_charset("utf8");
  33.    
  34.     # Security/Strictness
  35.     $maxHostsPerIP = 10; # Max unique games from same IP. Set to NULL for no limit.
  36.     $JSON_ForceType = Array(
  37.         "__addr" => is_string,
  38.         "__timeoutSec" => is_int,
  39.         "__rowPW" => is_string,
  40.         "__clientReqId" => is_int,
  41.         "gsoff" => is_int, "g" => is_string,
  42.         "n" => is_string, "m" => is_string,
  43.         "k" => is_int, "d" => is_string,
  44.         "t" => is_int, "r" => is_string,
  45.         "v" => is_string, "p" => is_string
  46.     );
  47.    
  48.     # What we send (if not NULL) to clients (BZ2).
  49.     $JSON_Send = Array("n", "m", "d", "t", "g", "r", "v", "k", "p", "__addr");
  50.    
  51.     # Strings we send to BZ2 which are JSON parameters.
  52.     function bz2_string($input) {
  53.         # Known bad characters: Backslash \, Double-Quote ".
  54.         return preg_replace("/[^\`\~\/\w\d\.\,\?\>\<\|\:\;\-\+\_\=\!\@\#\$\%\^\&\*\(\){}\[\]\']/" , "_", $input);
  55.     }
  56.    
  57.     # -------------------------------------------------------------------
  58.    
  59.     if ($reqMethod == "GET") {
  60.         # Remove timed out games, and give clients the game list.
  61.         if (isset($_GET["__gameId"])) {
  62.             $gameArray = Array();
  63.             $SQL = $SQLiDatabase->query("SELECT * FROM gamelist;") or die(mysqli_error($SQLiDatabase));
  64.             $SQL_Data = $SQL->fetch_all(MYSQLI_ASSOC); $SQL->free();
  65.             $now = time();
  66.            
  67.             if ($SQL_Data) {
  68.                 foreach($SQL_Data as $SQL_Row) {
  69.                     $clientLife = $now-$SQL_Row["__lastUpdate"];
  70.                     $clienetLifeSpan = $SQL_Row["__timeoutSec"]*$cfgMultTimeout;
  71.                    
  72.                     if ($clientLife > $clienetLifeSpan) {
  73.                         # This game has timed out.
  74.                         $SQLiDatabase->query("DELETE FROM gamelist WHERE __rowId=".$SQL_Row["__rowId"].";")
  75.                         or die(mysqli_error($SQLiDatabase));
  76.                     } elseif ($SQL_Row["gsoff"] == 0) {
  77.                         // $excludeCols = explode(",", $_GET["__excludeCols"]); // Wait, we don't send that junk anyways.
  78.                        
  79.                         $ToJSON = Array();
  80.                         foreach($SQL_Row as $column => $value) {
  81.                             if (($SQL_Row[$column] !== NULL) and (in_array($column, $JSON_Send))) {
  82.                                 $data = $SQL_Row[$column];
  83.                                 if ($JSON_ForceType[$column] === is_string) $data = "\"".bz2_string($data)."\"";
  84.                                 $ToJSON[] = "\"".$column."\":".$data;
  85.                             }
  86.                         }
  87.                        
  88.                         $gameArray[] = "{".implode(",", $ToJSON)."}";
  89.                     }
  90.                 }
  91.             }
  92.            
  93.             if (!is_null($cfgFakeLobbyName))
  94.                 $gameArray[] = "{\"n\":\"".$cfgFakeLobbyName."\",\"__addr\":\"0.0.0.0:0\",\"m\":\"\"}";
  95.            
  96.             $serverOutput .= "{\"GET\": [".implode(",", $gameArray)."], \"__request\":\"http://".$siteHostName."/testServer\"}";
  97.        
  98.         # Print version.
  99.         } elseif (isset($_GET["showVersion"])) {
  100.             $serverOutput .= "Version: <b>".$BZ2_SERVER_VERSION."</b>";
  101.        
  102.         # Use GSOff Feature, if enabled.
  103.         } elseif (isset($_GET["gsoff"])) {
  104.             if (!$cfgUseGsoff) {
  105.                 $serverOutput .= "Operation not supported on this server.";
  106.             } else {
  107.                 # Hide games listed by user's IP address in game list.
  108.                 $SQL = $SQLiDatabase->query("SELECT n, m FROM gamelist WHERE __addr=\"".$IP."\";")
  109.                 or die(mysqli_error($SQLiDatabase));
  110.                 $SQL_Data = $SQL->fetch_all(MYSQLI_ASSOC); $SQL->free();
  111.                 $count = count($SQL_Data);
  112.                
  113.                 if (!$count) die("No games found hosted by your IP.");
  114.                
  115.                 if ($_GET["gsoff"] == "1") {
  116.                     $gsoff = 1;
  117.                     $gsoff_str = "hidden";
  118.                 } else {
  119.                     $gsoff = 0;
  120.                     $gsoff_str = "visible";
  121.                 }
  122.                
  123.                 $SQLiDatabase->query("UPDATE gamelist SET gsoff=".$gsoff." WHERE __addr=\"".$IP."\";")
  124.                 or die(mysqli_error($SQLiDatabase));
  125.                 foreach($SQL_Data as $SQL_Row) {
  126.                     $serverOutput .= "Server <b>\"".$SQL_Row["n"]."\"</b> on <b>".
  127.                     $SQL_Row["m"].".bzn</b> now ".$gsoff_str.".<br>";
  128.                 }
  129.             }
  130.         }
  131.    
  132.     # Delete game from game list.
  133.     } elseif ($reqMethod == "DELETE") {
  134.         $rowID = (int)$_GET["__rowId"];
  135.         $rowPW = $SQLiDatabase->escape_string($_GET["__rowPW"]);
  136.         if ($rowID <= 0) die("Invalid Row ID.");
  137.         if (!$JSON_ForceType["__rowPW"]($rowPW)) die("Invalid Row Password.");
  138.        
  139.         $SQL = $SQLiDatabase->query("SELECT __rowPW FROM gamelist WHERE __rowId=".$rowID.";")
  140.         or die(mysqli_error($SQLiDatabase));
  141.         $SQL_Data = $SQL->fetch_array(MYSQLI_ASSOC); $SQL->free();
  142.         $ourRowPW = $SQL_Data["__rowPW"];
  143.        
  144.         if (is_null($ourRowPW)) die("Row does not exist.");
  145.         if ($rowPW !== $ourRowPW) die("Incorrect Row Password.");
  146.        
  147.         $SQLiDatabase->query("DELETE FROM gamelist WHERE __rowId=".$rowID.";") or die(mysqli_error($SQLiDatabase));
  148.    
  149.     # Add game to game list, or update existing game.
  150.     } elseif ($reqMethod == "POST") {
  151.         $POST_RawData = file_get_contents("php://input");
  152.         $JSON = json_decode($POST_RawData);
  153.         if (($JSON !== NULL) and ($JSON->{"__gameId"} !== NULL)) {
  154.                 if (is_int($maxHostsPerIP)) {
  155.                     $SQL = $SQLiDatabase->query("SELECT COUNT(*) FROM gamelist WHERE __addr=\"".$IP."\";")
  156.                     or die(mysqli_error($SQLiDatabase));
  157.                     $SQL_Data = $SQL->fetch_all(MYSQLI_NUM); $SQL->free();
  158.                     if ($SQL_Data[0][0] >= $maxHostsPerIP) die("Maximum hosts per IP reached.");
  159.                 }
  160.                
  161.                 $SQL = $SQLiDatabase->query("SELECT __rowId, __rowPW FROM gamelist WHERE __clientReqId=".$JSON->{"__clientReqId"}.";")
  162.                 or die(mysqli_error($SQLiDatabase));
  163.                 $SQL_Data = $SQL->fetch_array(MYSQLI_ASSOC); $SQL->free();
  164.                 $rowID = (!is_null($SQL_Data)) ? $SQL_Data["__rowId"] : NULL;
  165.                
  166.                 $NewData = Array();
  167.                 foreach ($JSON as $key => $data) {
  168.                     # Only add values we expect from BZ2, and
  169.                     # validate their type. Also escape all strings.
  170.                     if (array_key_exists($key, $JSON_ForceType)) {
  171.                         if (!$JSON_ForceType[$key]($data)) die($key." is invalid type.");
  172.                        
  173.                         if (is_string($data)) {
  174.                             $JSON->{$key} = $SQLiDatabase->escape_string($data);
  175.                             $data = "\"".$JSON->{$key}."\"";
  176.                         }
  177.                        
  178.                         $NewData[$key] = $data;
  179.                     }
  180.                 }
  181.                 $NewData["__addr"] = "\"".$IP."\"";
  182.                 $NewData["__lastUpdate"] = time();
  183.                
  184.                 if(is_null($rowID)) {
  185.                     # List new game.
  186.                     $SQL_Key = Array(); $SQL_Val = Array();
  187.                     foreach($NewData as $key => $val) {
  188.                         $SQL_Key[] = $key; $SQL_Val[] = $val;
  189.                     }
  190.                     $SQL_Command = "INSERT INTO gamelist (".implode(", ", $SQL_Key).") VALUES (".implode(", ", $SQL_Val).");";
  191.                     $rowID = 0;
  192.                 } elseif ($SQL_Data["__rowPW"] === $JSON->{"__rowPW"}) {
  193.                     # Update existing game.
  194.                     $SQL_Set = Array();
  195.                     foreach($NewData as $key => $val) {
  196.                         $SQL_Set[] = $key."=".$val;
  197.                     }
  198.                     $SQL_Command = "UPDATE gamelist SET ".implode(", ", $SQL_Set)." WHERE __rowId=".$rowID.";";
  199.                 } else die("Bad Request.");
  200.                
  201.                 $SQLiDatabase->query($SQL_Command) or die(mysqli_error($SQLiDatabase));
  202.                 if ($rowID === 0) $rowID = $SQLiDatabase->insert_id;
  203.                
  204.                 # Response for BZ2 so it knows to send DELETE.
  205.                 $serverOutput .= "{\"POST\":\r\n".
  206.                 "{\"__clientReqId\":\"".$JSON->{"__clientReqId"}.
  207.                 "\",\"__rowId\":".$rowID.
  208.                 ",\"__gameId\":\"BZ2\"}\r\n".
  209.                 "}\r\n";
  210.         } else die("Invalid JSON.");
  211.     }
  212.    
  213.     $SQLiDatabase->close();
  214.    
  215.     # Specify content length to ensure server does
  216.     # not use chunked encoding. (Crashes winXP clients.)
  217.     header("Content-Length: ".strlen($serverOutput));
  218.     echo $serverOutput;
  219. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement