Implemented OpenClonk update System, updated files, updated to version 1.2.0

Benedict Etzel 2010-11-17 18:55:37 +01:00
parent a49116bdc4
commit 62e17d2499
8 changed files with 427 additions and 334 deletions

View File

@ -7,27 +7,38 @@ The installation should now be complete and ready to use. You can see the server
__Database__ __Database__
CREATE TABLE IF NOT EXISTS `c4ms_flood` ( CREATE TABLE `c4ms_flood` (
`ip` char(32) NOT NULL, `ip` char(32) CHARACTER SET latin1 NOT NULL,
`count` int(11) NOT NULL, `count` int(11) NOT NULL,
`time` char(20) NOT NULL, `time` char(20) CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`ip`) PRIMARY KEY (`ip`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `c4ms_games` (
CREATE TABLE IF NOT EXISTS `c4ms_games` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(255) NOT NULL, `ip` varchar(255) CHARACTER SET latin1 NOT NULL,
`csid` varchar(255) NOT NULL, `csid` varchar(255) CHARACTER SET latin1 NOT NULL,
`data` text NOT NULL, `data` text CHARACTER SET latin1 NOT NULL,
`start` varchar(255) NOT NULL, `start` varchar(255) CHARACTER SET latin1 NOT NULL,
`time` varchar(255) NOT NULL, `time` varchar(255) CHARACTER SET latin1 NOT NULL,
`valid` tinyint(4) NOT NULL, `valid` tinyint(4) NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
__Updates__
If you are running an update service for OpenClonk, you also need to insert the following table and specifiy the config entries. (see there for more details)
CREATE TABLE `c4ms_update` (
`old_version` varchar(16) CHARACTER SET latin1 NOT NULL,
`new_version` varchar(16) CHARACTER SET latin1 NOT NULL,
`platform` varchar(64) CHARACTER SET latin1 NOT NULL,
`file` varchar(255) CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`old_version`,`platform`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
__License__ __License__
This work is licensed under the Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. This work is licensed under the Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
__Append__ __Append__
Please also note that 'Clonk' is a registered trademark of Matthes Bender (http://www.clonk.de) Please also note that 'Clonk' is a registered trademark of Matthes Bender (http://www.clonk.de).

View File

@ -3,7 +3,7 @@
* C4Masterserver main frontend * C4Masterserver main frontend
* *
* @package C4Masterserver * @package C4Masterserver
* @version 1.1.5-en * @version 1.2.0-en
* @author Benedict Etzel <b.etzel@live.de> * @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/ */
@ -17,46 +17,46 @@ require_once('server/include/ParseINI.php');
$config = file_get_contents('server/include/config.ini'); $config = file_get_contents('server/include/config.ini');
$link = mysql_connect( $link = mysql_connect(
ParseINI::ParseValue('mysql_host', $config), ParseINI::parseValue('mysql_host', $config),
ParseINI::ParseValue('mysql_user', $config), ParseINI::parseValue('mysql_user', $config),
ParseINI::ParseValue('mysql_password', $config)); //connect to MySQL ParseINI::parseValue('mysql_password', $config)); //connect to MySQL
$db = mysql_selectdb(ParseINI::ParseValue('mysql_db', $config), $link); //select the database $db = mysql_selectdb(ParseINI::parseValue('mysql_db', $config), $link); //select the database
if($link && $db) { if($link && $db) {
$server = new C4Masterserver($link, ParseINI::ParseValue('mysql_prefix', $config)); $server = new C4Masterserver($link, $config);
$server->SetTimeoutgames(intval(ParseINI::ParseValue('c4ms_timeoutgames', $config))); $server->setTimeoutgames(intval(ParseINI::parseValue('c4ms_timeoutgames', $config)));
$server->SetDeletegames(intval(ParseINI::ParseValue('c4ms_deletegames', $config))); $server->setDeletegames(intval(ParseINI::parseValue('c4ms_deletegames', $config)));
$server->SetMaxgames(intval(ParseINI::ParseValue('c4ms_maxgames', $config))); $server->setMaxgames(intval(ParseINI::parseValue('c4ms_maxgames', $config)));
$protect = new FloodProtection($link, ParseINI::ParseValue('mysql_prefix', $config)); $protect = new FloodProtection($link, ParseINI::parseValue('mysql_prefix', $config));
$protect->SetMaxflood(intval(ParseINI::ParseValue('flood_maxrequests', $config))); $protect->setMaxflood(intval(ParseINI::parseValue('flood_maxrequests', $config)));
if($protect->CheckRequest($_SERVER['REMOTE_ADDR'])) { //flood protection if($protect->checkRequest($_SERVER['REMOTE_ADDR'])) { //flood protection
header('Content-Type: text/plain'); header('Content-Type: text/plain');
die('Flood protection.'); die('Flood protection.');
} }
$games = ''; $games = '';
$list = $server->GetReferenceArray(true); $list = $server->getReferenceArray(true);
$players = ''; $players = '';
$count = 0; $count = 0;
foreach($list as $reference) { foreach($list as $reference) {
if($reference['valid']) { if($reference['valid']) {
$games .= '<tr>'; $games .= '<tr>';
$games .= '<td>'.htmlspecialchars(ParseINI::ParseValue('Title', $reference['data'])).'</td>'; $games .= '<td>'.htmlspecialchars(ParseINI::parseValue('Title', $reference['data'])).'</td>';
$games .= '<td>'.htmlspecialchars(ParseINI::ParseValue('State', $reference['data'])).'</td>'; $games .= '<td>'.htmlspecialchars(ParseINI::parseValue('State', $reference['data'])).'</td>';
$games .= '<td>'.date("Y-m-d H:i", $reference['start']).'</td>'; $games .= '<td>'.date("Y-m-d H:i", $reference['start']).'</td>';
$players = ''; $players = '';
$player_list = ParseINI::ParseValuesByCategory('Name', 'Player', $reference['data']); $player_list = ParseINI::parseValuesByCategory('Name', 'Player', $reference['data']);
foreach($player_list as $player) { foreach($player_list as $player) {
if(!empty($players)) $players .= ', '; if(!empty($players)) $players .= ', ';
$players .= $player; $players .= $player;
} }
$games .= '<td>'.htmlspecialchars($players).'</td>'; $games .= '<td>'.htmlspecialchars($players).'</td>';
} }
if((ParseINI::ParseValue('State', $reference['data']) == 'Running') && $reference['time'] >= time() - 60*60*24) { if((ParseINI::parseValue('State', $reference['data']) == 'Running') && $reference['time'] >= time() - 60*60*24) {
$count++; $count++;
} }
} }
$games = C4Network::CleanString($games); $games = C4Network::cleanString($games);
$server->CleanUp(); $server->cleanUp();
} }
$dirname = dirname($_SERVER['SCRIPT_NAME']); $dirname = dirname($_SERVER['SCRIPT_NAME']);
@ -67,7 +67,7 @@ if($dirname != '/') {
$dirname .= $path.'server/'; $dirname .= $path.'server/';
$server_link = strtolower($_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$dirname); $server_link = strtolower($_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$dirname);
$engine = ''; $engine = '';
$engine_string = ParseINI::ParseValue('c4ms_engine', $config); $engine_string = ParseINI::parseValue('c4ms_engine', $config);
if(!empty($engine_string)) { if(!empty($engine_string)) {
$engine = '('.$engine_string.' only)'; $engine = '('.$engine_string.' only)';
} }
@ -117,7 +117,7 @@ if(!empty($engine_string)) {
} }
?> ?>
<div id="masterserver_footer"> <div id="masterserver_footer">
<p>Powered by C4Masterserver v<?php echo C4Masterserver::GetVersion(); ?> &bull; Coded by Benedict Etzel</p> <p>Powered by C4Masterserver v<?php echo C4Masterserver::GetVersion(); ?> &raquo; Coded by Benedict Etzel</p>
</div> </div>
</div> </div>
</body> </body>

View File

@ -1,187 +1,199 @@
<?php <?php
/**
* Provides functionality to add, update and remove
* game references based on a MySQL table.
*
* @package C4Masterserver
* @version 1.1.5-en
* @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/
class C4Masterserver {
/** /**
* Stores the masterserver version. * Provides functionality to add, update and remove
* * game references based on a MySQL table.
* @var string *
*/ * @package C4Masterserver
static public $version = '1.1.5'; * @version 1.2.0-en
* @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/
class C4Masterserver {
/** /**
* Stores the MySQL connection resource. * Stores the masterserver version.
* *
* @var resource * @var string
*/ */
private $link; static public $version = '1.2.0';
/**
* Stores the MySQL connection resource.
*
* @var resource
*/
private $link;
/**
* Stores the MySQL table prefix.
*
* @var string
*/
private $config;
/**
* Stores the seconds after which games timeout.
*
* @var int
*/
private $timeoutgames;
/**
* Stores the seconds after which games are removed.
*
* @var int
*/
private $deletegames;
/**
* Stores the maximum amount of games per ip.
*
* @var int
*/
private $maxgames;
/** /**
* Stores the MySQL table prefix. * The C4Masterserver constructor.
* *
* @var string * @param resource $link
*/ * @return C4Masterserver
private $prefix; */
public function __construct($link, $config) {
$this->link = $link;
$this->config = $config;
$this->timeoutgames = 600;
$this->deletegames = 60 * 60 * 24;
$this->maxgames = 5;
}
/** /**
* Stores the seconds after which games timeout. * Returns the C4Masterserver version.
* *
* @var int * @param void
*/ * @return string
private $timeoutgames; */
public static function getVersion() {
return(C4Masterserver::$version);
}
/** /**
* Stores the seconds after which games are removed. * Sets the seconds after which games timeout.
* *
* @var int * @param int $timeoutgames
*/ * @return void
private $deletegames; */
public function setTimeoutgames($timeoutgames) {
$this->timeoutgames = $timeoutgames;
}
/** /**
* Stores the maximum amount of games per ip. * Sets the seconds after which games are removed.
* *
* @var int * @param int $deletegames
*/ * @return void
private $maxgames; */
public function setDeletegames($deletegames) {
$this->deletegames = $deletegames;
}
/**
* Sets the maximum amount of games per ip.
*
* @param int $maxgames
* @return void
*/
public function setMaxgames($maxgames) {
$this->maxgames = $maxgames;
}
/** /**
* The C4Masterserver constructor. * Returns all valid references. If $show_all is true, it returns all references.
* *
* @param resource $link * @param bool $show_all
* @return C4Masterserver * @return array
*/ */
public function __construct($link, $prefix) { public function getReferenceArray($show_all = false) {
$this->link = $link; if (!$this->link)
$this->prefix = $prefix; return false;
$this->timeoutgames = 600; $append = $show_all ? '' : 'WHERE `valid` = \'1\'';
$this->deletegames = 60*60*24; $result = mysql_query('SELECT * FROM `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games`' . $append);
$this->maxgames = 5; $list = array();
} while ($row = mysql_fetch_assoc($result)) {
$list[$row['id']] = $row;
}
return $list;
}
/** /**
* Returns the C4Masterserver version. * Adds a new reference and returns the new CSID.
* *
* @param void * @param string $reference
* @return string * @return string
*/ */
public static function GetVersion() { public function addReference($reference) {
return(C4Masterserver::$version); if (!$this->link)
} return false;
$reference = str_replace('0.0.0.0', $_SERVER['REMOTE_ADDR'], $reference);
$query = mysql_query('SELECT * FROM `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games` WHERE `ip` = \'' . $_SERVER['REMOTE_ADDR'] . '\' AND `valid` = \'1\'', $this->link);
if (mysql_num_rows($query) > $this->maxgames) {
return false;
}
$csid = sha1(uniqid(mt_rand(), true));
mysql_query('INSERT INTO `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games` (`id`, `ip`,`csid`, `data`, `start`, `time`, `valid`) VALUES (\'\', \'' . $_SERVER['REMOTE_ADDR'] . '\', \'' . $csid . '\', \'' . $reference . '\', \'' . time() . '\', \'' . time() . '\', \'1\')', $this->link);
return $csid;
}
/** /**
* Sets the seconds after which games timeout. * Updates a reference.
* *
* @param int $timeoutgames * @param string $csid
* @return void * @param string $newreference
*/ * @return bool
public function SetTimeoutgames($timeoutgames) { */
$this->timeoutgames = $timeoutgames; public function updateReference($csid, $newreference) {
} if (!$this->link)
return false;
$newreference = str_replace('0.0.0.0', $_SERVER['REMOTE_ADDR'], $newreference);
mysql_query('UPDATE `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games` SET `data`=\'' . $newreference . '\',`time` = \'' . time() . '\', `valid` = \'1\' WHERE `csid` = \'' . $csid . '\'', $this->link);
return true;
}
/** /**
* Sets the seconds after which games are removed. * Removes a reference by setting it invalid.
* *
* @param int $deletegames * @param string $csid
* @return void * @return bool
*/ */
public function SetDeletegames($deletegames) { public function removeReference($csid) {
$this->deletegames = $deletegames; if (!$this->link)
} return false;
mysql_query('UPDATE `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games` SET `time` = \'' . time() . '\', `valid` = \'0\' WHERE `csid` = \'' . $csid . '\'', $this->link);
return true;
}
/** /**
* Sets the maximum amount of games per ip. * Sets old references invalid and removes very old ones if $remove is true.
* *
* @param int $maxgames * @param void
* @return void * @return void
*/ */
public function SetMaxgames($maxgames) { public function cleanUp() {
$this->maxgames = $maxgames; if (!$this->link)
} return false;
if ($this->timeoutgames != 0) {
mysql_query('UPDATE `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games` SET `valid` = \'0\' WHERE `time` < \'' . (time() - $this->timeoutgames) . '\'', $this->link);
}
if ($this->deletegames != 0) {
mysql_query('DELETE FROM `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'games` WHERE `valid` = \'0\' AND `time` < \'' . (time() - $this->deletegames) . '\'', $this->link);
}
}
/** public function getDownloadURL($platform) {
* Returns all valid references. If $show_all is true, it returns all references. $result = mysql_query('SELECT `file` FROM `' . ParseINI::parseValue('mysql_prefix', $this->config) . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\'');
* if ($result) {
* @param bool $show_all $row = mysql_fetch_assoc($result);
* @return array if ($row['file'])
*/ return ParseINI::parseValue('oc_update_url', $this->config) . $row['file'];
public function GetReferenceArray($show_all = false) { }
if(!$this->link) return false; return false;
$append = $show_all ? '' : 'WHERE `valid` = \'1\''; }
$result = mysql_query('SELECT * FROM `'.$this->prefix.'games`'.$append);
$list = array();
while($row = mysql_fetch_assoc($result)) {
$list[$row['id']] = $row;
}
return $list;
}
/** }
* Adds a new reference and returns the new CSID.
*
* @param string $reference
* @return string
*/
public function AddReference($reference) {
if(!$this->link) return false;
$reference = str_replace('0.0.0.0', $_SERVER['REMOTE_ADDR'], $reference);
$query = mysql_query('SELECT * FROM `'.$this->prefix.'games` WHERE `ip` = \''.$_SERVER['REMOTE_ADDR'].'\' AND `valid` = \'1\'', $this->link);
if(mysql_num_rows($query) > $this->maxgames) {
return false;
}
$csid = sha1(uniqid(mt_rand(), true));
mysql_query('INSERT INTO `'.$this->prefix.'games` (`id`, `ip`,`csid`, `data`, `start`, `time`, `valid`) VALUES (\'\', \''.$_SERVER['REMOTE_ADDR'].'\', \''.$csid.'\', \''.$reference.'\', \''.time().'\', \''.time().'\', \'1\')', $this->link);
return $csid;
}
/**
* Updates a reference.
*
* @param string $csid
* @param string $newreference
* @return bool
*/
public function UpdateReference($csid, $newreference) {
if(!$this->link) return false;
$newreference = str_replace('0.0.0.0', $_SERVER['REMOTE_ADDR'], $newreference);
mysql_query('UPDATE `'.$this->prefix.'games` SET `data`=\''.$newreference.'\',`time` = \''.time().'\', `valid` = \'1\' WHERE `csid` = \''.$csid.'\'', $this->link);
return true;
}
/**
* Removes a reference by setting it invalid.
*
* @param string $csid
* @return bool
*/
public function RemoveReference($csid) {
if(!$this->link) return false;
mysql_query('UPDATE `'.$this->prefix.'games` SET `time` = \''.time().'\', `valid` = \'0\' WHERE `csid` = \''.$csid.'\'', $this->link);
return true;
}
/**
* Sets old references invalid and removes very old ones if $remove is true.
*
* @param void
* @return void
*/
public function CleanUp() {
if(!$this->link) return false;
if($this->timeoutgames != 0) {
mysql_query('UPDATE `'.$this->prefix.'games` SET `valid` = \'0\' WHERE `time` < \''.(time() - $this->timeoutgames).'\'', $this->link);
}
if($this->deletegames != 0) {
mysql_query('DELETE FROM `'.$this->prefix.'games` WHERE `valid` = \'0\' AND `time` < \''.(time() - $this->deletegames).'\'', $this->link);
}
}
}
?> ?>

View File

@ -4,7 +4,7 @@
* Clonk 4 engine with ini-style strings. * Clonk 4 engine with ini-style strings.
* *
* @package C4Masterserver * @package C4Masterserver
* @version 1.1.5-en * @version 1.2.0-en
* @author Benedict Etzel <b.etzel@live.de> * @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/ */
@ -16,7 +16,7 @@ abstract class C4Network {
* @param array $data * @param array $data
* @return string * @return string
*/ */
public static function CreateAnswer($data) { public static function createAnswer($data) {
$message = '[Response]'."\n"; $message = '[Response]'."\n";
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
$message .= $key.'='.$value."\n"; $message .= $key.'='.$value."\n";
@ -30,8 +30,8 @@ abstract class C4Network {
* @param string message * @param string message
* @return string * @return string
*/ */
public static function CreateError($message) { public static function createError($message) {
return C4Network::CreateAnswer(array("Status" => "Failure", "Message" => $message)); return C4Network::createAnswer(array("Status" => "Failure", "Message" => $message));
} }
/** /**
@ -40,8 +40,8 @@ abstract class C4Network {
* @param string $message * @param string $message
* @return void * @return void
*/ */
public static function SendAnswer($message) { public static function sendAnswer($message) {
//header('Content-Length: '.strlen($message)); header('Content-Length: '.strlen($message));
echo $message; echo $message;
} }
@ -51,12 +51,12 @@ abstract class C4Network {
* @param string $message * @param string $message
* @return string * @return string
*/ */
public static function CleanString($message) { public static function cleanString($message) {
$coded = $decoded = array(); $coded = $decoded = array();
preg_match_all('|\\\[0-9]{3}|', $message, $coded); preg_match_all('|\\\[0-9]{3}|', $message, $coded);
foreach($coded[0] as $numstr) { foreach($coded[0] as $numstr) {
$num = ereg_replace("[^0-9]", "", $numstr); $num = ereg_replace("[^0-9]", "", $numstr);
$decoded[$num] = C4Network::DecodeEntitiyString($num); $decoded[$num] = C4Network::decodeEntitiyString($num);
} }
foreach($decoded as $num => $entity) { foreach($decoded as $num => $entity) {
$message = str_replace('\\'.$num, $entity, $message); $message = str_replace('\\'.$num, $entity, $message);
@ -70,7 +70,7 @@ abstract class C4Network {
* @param string $string * @param string $string
* @return string * @return string
*/ */
public static function DecodeEntitiyString($string) { public static function decodeEntitiyString($string) {
$num = ereg_replace("[^0-9]", "", $string); $num = ereg_replace("[^0-9]", "", $string);
$num = octdec($num); $num = octdec($num);
return iconv('Windows-1252', 'UTF-8', chr($num)); return iconv('Windows-1252', 'UTF-8', chr($num));

View File

@ -4,7 +4,7 @@
* flooding attempts by ip. * flooding attempts by ip.
* *
* @package C4Masterserver * @package C4Masterserver
* @version 1.1.5-en * @version 1.2.0-en
* @author Benedict Etzel <b.etzel@live.de> * @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/ */
@ -49,7 +49,7 @@ class FloodProtection {
* @param int $maxflood * @param int $maxflood
* @return void * @return void
*/ */
public function SetMaxflood($maxflood) { public function setMaxflood($maxflood) {
$this->maxflood = $maxflood; $this->maxflood = $maxflood;
} }
@ -59,7 +59,7 @@ class FloodProtection {
* @param string $ip * @param string $ip
* @return bool * @return bool
*/ */
public function CheckRequest($ip) { public function checkRequest($ip) {
if(!$this->link) return false; if(!$this->link) return false;
if($this->UserKnown($ip)) { if($this->UserKnown($ip)) {
$this->UpdateUser($ip); $this->UpdateUser($ip);
@ -77,7 +77,7 @@ class FloodProtection {
* @param string $ip * @param string $ip
* @return bool * @return bool
*/ */
private function UserKnown($ip) { private function userKnown($ip) {
if(!$this->link) return false; if(!$this->link) return false;
$query = mysql_query('SELECT `time` FROM `'.$this->prefix.'flood` WHERE `ip` = \' '.$ip. '\' LIMIT 1', $this->link); $query = mysql_query('SELECT `time` FROM `'.$this->prefix.'flood` WHERE `ip` = \' '.$ip. '\' LIMIT 1', $this->link);
if(mysql_num_rows($query) > 0) { if(mysql_num_rows($query) > 0) {
@ -92,7 +92,7 @@ class FloodProtection {
* @param string $ip * @param string $ip
* @return bool * @return bool
*/ */
private function AddUser($ip) { private function addUser($ip) {
if(!$this->link) return false; if(!$this->link) return false;
$query = mysql_query('INSERT INTO `'.$this->prefix.'flood` (`ip`, `count`, `time`) VALUES (\' '.$ip. '\', \'0\',\''. time() .'\') ', $this->link); $query = mysql_query('INSERT INTO `'.$this->prefix.'flood` (`ip`, `count`, `time`) VALUES (\' '.$ip. '\', \'0\',\''. time() .'\') ', $this->link);
if(!$query) { if(!$query) {
@ -107,7 +107,7 @@ class FloodProtection {
* @param string $ip * @param string $ip
* @return bool * @return bool
*/ */
private function UpdateUser($ip) { private function updateUser($ip) {
if(!$this->link) return false; if(!$this->link) return false;
mysql_query('UPDATE `'.$this->prefix.'flood` SET `count` = \'0\' WHERE `ip` = \' '.$ip.'\' AND `time` != \''.time().'\'', $this->link); mysql_query('UPDATE `'.$this->prefix.'flood` SET `count` = \'0\' WHERE `ip` = \' '.$ip.'\' AND `time` != \''.time().'\'', $this->link);
mysql_query('UPDATE `'.$this->prefix.'flood` SET `count` = `count`+\'1\', `time` = \''.time().'\' WHERE `ip` = \' '. mysql_real_escape_string($ip, $this->link).'\'', $this->link); mysql_query('UPDATE `'.$this->prefix.'flood` SET `count` = `count`+\'1\', `time` = \''.time().'\' WHERE `ip` = \' '. mysql_real_escape_string($ip, $this->link).'\'', $this->link);
@ -119,7 +119,7 @@ class FloodProtection {
* @param string $ip * @param string $ip
* @return bool * @return bool
*/ */
private function UserFlooding($ip) { private function userFlooding($ip) {
if(!$this->link) return false; if(!$this->link) return false;
$query = mysql_query('SELECT `time` FROM `'.$this->prefix.'flood` WHERE `ip` = \' '.$ip.'\' AND `count` >= \''.$this->maxflood.'\' LIMIT 1', $this->link); $query = mysql_query('SELECT `time` FROM `'.$this->prefix.'flood` WHERE `ip` = \' '.$ip.'\' AND `count` >= \''.$this->maxflood.'\' LIMIT 1', $this->link);
if(mysql_num_rows($query) > 0) { if(mysql_num_rows($query) > 0) {
@ -133,7 +133,7 @@ class FloodProtection {
* *
* @return void * @return void
*/ */
private function CleanUp() { private function cleanUp() {
mysql_query('DELETE FROM `'.$this->prefix.'flood` WHERE `time` <= \'' . (time()- 600) . '\'', $this->link); mysql_query('DELETE FROM `'.$this->prefix.'flood` WHERE `time` <= \'' . (time()- 600) . '\'', $this->link);
} }
} }

View File

@ -4,7 +4,7 @@
* from an ini-like string. * from an ini-like string.
* *
* @package C4Masterserver * @package C4Masterserver
* @version 1.1.5-en * @version 1.2.0-en
* @author Benedict Etzel <b.etzel@live.de> * @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/ */
@ -17,7 +17,7 @@ abstract class ParseINI {
* @param string $string * @param string $string
* @return string * @return string
*/ */
public static function ParseValue($key, $string) { public static function parseValue($key, $string) {
if(!$key || !$string) { if(!$key || !$string) {
return false; return false;
} }
@ -34,7 +34,10 @@ abstract class ParseINI {
$value = substr($string, $key_start, $key_end - $key_start); $value = substr($string, $key_start, $key_end - $key_start);
} }
$value = trim($value); $value = trim($value);
return trim($value, '"'); $value = trim($value, '"');
if($value == 'true') $value = 1;
if($value == 'false') $value = 0;
return $value;
} }
/** /**
@ -45,7 +48,7 @@ abstract class ParseINI {
* @param string $string * @param string $string
* @return array * @return array
*/ */
public static function ParseValuesByCategory($key, $category, $string) { public static function parseValuesByCategory($key, $category, $string) {
if(!$key || !$string || !$category) { if(!$key || !$string || !$category) {
return false; return false;
} }
@ -65,9 +68,7 @@ abstract class ParseINI {
if($current_category != $category) continue; //wrong category if($current_category != $category) continue; //wrong category
if(strpos($line, ';') === 0) continue; //comment if(strpos($line, ';') === 0) continue; //comment
if(strpos($line, $key) === false) continue; //not needed if(strpos($line, $key) === false) continue; //not needed
$value = ParseINI::ParseValue($key, $line); $values[] = ParseINI::parseValue($key, $line);
$value = trim($value);
$values[] = trim($value, '"');
} }
return $values; return $values;
} }

View File

@ -14,17 +14,35 @@ mysql_db=c4ms
;your MySQL prefix, default c4ms_ ;your MySQL prefix, default c4ms_
mysql_prefix=c4ms_ mysql_prefix=c4ms_
;accepted engine strings, leave empty to allow all (Example: OpenClonk) ;accepted engine strings, has to be set (Example: OpenClonk)
c4ms_title_engine=OpenClonk
;accepted engine strings (to forbid certain engines), leave empty to allow all (Example: OpenClonk)
c4ms_engine= c4ms_engine=
;seconds after timing out old games, default 60*10 = 600 ;message of the day (shown in the network screen)
c4ms_timeoutgames=600 c4ms_motd=<c 0fff0f>Which is worse: ignorance or apathy? Who knows? Who cares?</c>
;seconds after timing out old games, default 60*3 = 180
c4ms_timeoutgames=180
;seconds after deleting old games, default 60*60*24 = 86400 ;seconds after deleting old games, default 60*60*24 = 86400
c4ms_deletegames=86400 c4ms_deletegames=86400
;maximum alloud games per ip, default 5 ;maximum alloud games per ip, default 1
c4ms_maxgames=5 c4ms_maxgames=1
;maximum alloud requests per second, default 5 ;maximum alloud requests per second, default 5
flood_maxrequests=5 flood_maxrequests=5
;enable the OpenClonk update system, default 0
oc_enable_update=false
;path to the update files
oc_update_path=
;url to the update files with trailing slash, shouldn't be empty
oc_update_url=http://www.example.com/
;secret key for the HAMC-updating system (using sha256) to verify files
oc_update_secret=

View File

@ -1,107 +1,158 @@
<?php <?php
/**
* C4Masterserver engine backend
*
* @package C4Masterserver
* @version 1.1.5-en
* @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/
//error_reporting(E_NONE); //suppress errors /**
* C4Masterserver engine backend
*
* @package C4Masterserver
* @version 1.2.0-en
* @author Benedict Etzel <b.etzel@live.de>
* @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
*/
//error_reporting(E_ALL); //suppress errors
require_once('include/C4Masterserver.php'); require_once('include/C4Masterserver.php');
require_once('include/C4Network.php'); require_once('include/C4Network.php');
require_once('include/FloodProtection.php'); require_once('include/FloodProtection.php');
require_once('include/ParseINI.php'); require_once('include/ParseINI.php');
$config = file_get_contents('include/config.ini'); $config = file_get_contents('include/config.ini');
$link = mysql_connect( $link = mysql_connect(
ParseINI::ParseValue('mysql_host', $config), ParseINI::parseValue('mysql_host', $config),
ParseINI::ParseValue('mysql_user', $config), ParseINI::parseValue('mysql_user', $config),
ParseINI::ParseValue('mysql_password', $config)); //connect to MySQL ParseINI::parseValue('mysql_password', $config)); //connect to MySQL
$db = mysql_selectdb(ParseINI::ParseValue('mysql_db', $config), $link); //select the database $db = mysql_selectdb(ParseINI::parseValue('mysql_db', $config), $link); //select the database
header('Content-Type: text/plain'); //output as plain text header('Content-Type: text/plain'); //output as plain text
if($link && $db) { if ($link && $db) {
$server = new C4Masterserver($link, ParseINI::ParseValue('mysql_prefix', $config)); $prefix = ParseINI::parseValue('mysql_prefix', $config);
$server->SetTimeoutgames(intval(ParseINI::ParseValue('c4ms_timeoutgames', $config))); $server = new C4Masterserver($link, $config);
$server->SetDeletegames(intval(ParseINI::ParseValue('c4ms_deletegames', $config))); $server->setTimeoutgames(intval(ParseINI::parseValue('c4ms_timeoutgames', $config)));
$server->SetMaxgames(intval(ParseINI::ParseValue('c4ms_maxgames', $config))); $server->setDeletegames(intval(ParseINI::parseValue('c4ms_deletegames', $config)));
$protect = new FloodProtection($link, ParseINI::ParseValue('mysql_prefix', $config)); $server->setMaxgames(intval(ParseINI::parseValue('c4ms_maxgames', $config)));
$protect->SetMaxflood(intval(ParseINI::ParseValue('flood_maxrequests', $config))); $protect = new FloodProtection($link, $prefix);
if($protect->CheckRequest($_SERVER['REMOTE_ADDR'])) { //flood protection $protect->setMaxflood(intval(ParseINI::parseValue('flood_maxrequests', $config)));
C4Network::SendAnswer(C4Network::CreateError('Flood protection.')); if ($protect->checkRequest($_SERVER['REMOTE_ADDR'])) { //flood protection
die(); C4Network::sendAnswer(C4Network::createError('Flood protection.'));
} die();
$server->CleanUp(true); //Cleanup old stuff }
if(isset($GLOBALS['HTTP_RAW_POST_DATA'])) { //data sent from engine? $server->cleanUp(true); //Cleanup old stuff
$input = $GLOBALS['HTTP_RAW_POST_DATA']; if (ParseINI::parseValue('oc_enable_update', $config) == 1 && isset($_GET['action']) && $_GET['action'] == 'release-file' && isset($_GET['file']) && isset($_GET['hash']) && isset($_GET['new_version']) && isset($_GET['platform'])) {
$action = ParseINI::ParseValue('Action', $input); $file = ParseINI::parseValue('oc_update_path', $config) . $_GET['file'];
$csid = ParseINI::ParseValue('CSID', $input); if (file_exists($file) && hash_hmac_file('sha256', $file, ParseINI::parseValue('oc_update_secret', $config)) == $_GET['hash']) {
$csid = mysql_real_escape_string($csid, $link); $old_version = isset($_GET['old_version']) ? explode(',', mysql_real_escape_string($_GET['old_version'], $link)) : array();
$reference = mysql_real_escape_string(strstr($input, '[Reference]'), $link); $new_version = mysql_real_escape_string($_GET['new_version'], $link);
$engine_string = ParseINI::ParseValue('c4ms_engine', $config); $platform = mysql_real_escape_string($_GET['platform'], $link);
if(empty($engine_string) || ParseINI::ParseValue('Game', $input) == $engine_string) { $file = mysql_real_escape_string($file, $link);
switch($action) { if (!empty($old_version)) {
case 'Start': //start a new round if (isset($_GET['delete_old_files']) && $_GET['delete_old_files'] == 'yes') {
if(ParseINI::ParseValue('LeagueAddress', $reference)) { $result = mysql_query('SELECT `file` FROM `' . $prefix . 'update` WHERE `new_version` != \'' . $new_version . '\' AND `old_version` != \'\' AND `platform` = \'' . $platform . '\'');
C4Network::SendAnswer(C4Network::CreateError('League not supported!')); while (($row = mysql_fetch_assoc($result)) != false) {
} unlink(ParseINI::parseValue('oc_update_path', $config) . $row['file']);
else { }
$csid = $server->AddReference($reference); }
if($csid) { mysql_query('DELETE FROM `' . $prefix . 'update` WHERE `new_version` != \'' . $new_version . '\' AND `old_version` != \'\' AND `platform` = \'' . $platform . '\'');
C4Network::SendAnswer(C4Network::CreateAnswer(array('Status' => 'Success', 'CSID' => $csid))); foreach ($old_version as $version) {
} mysql_query('INSERT INTO `' . $prefix . 'update` (`old_version`, `new_version`, `platform`, `file`) VALUES (\'' . $version . '\', \'' . $new_version . '\', \'' . $platform . '\', \'' . $file . '\')');
else { }
C4Network::SendAnswer(C4Network::CreateError('Round signup failed. (To many tries?)')); } else {
} if (isset($_GET['delete_old_files']) && $_GET['delete_old_files'] == 'yes') {
} $row = mysql_fetch_assoc(mysql_query('SELECT `file` FROM `' . $prefix . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\''));
break; unlink(ParseINI::parseValue('oc_update_path', $config) . $row['file']);
case 'Update': //update an existing round }
if($server->UpdateReference($csid, $reference)) { mysql_query('DELETE FROM `' . $prefix . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\'');
C4Network::SendAnswer(C4Network::CreateAnswer(array('Status' => 'Success'))); mysql_query('INSERT INTO `' . $prefix . 'update` (`old_version`, `new_version`, `platform`, `file`) VALUES (\'\', \'' . $new_version . '\', \'' . $platform . '\', \'' . $file . '\')');
} }
else { } else {
C4Network::SendAnswer(C4Network::CreateError('Round update failed.')); C4Network::sendAnswer(C4Network::createError('File not found or hash incorrect.'));
} }
break; } else if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) { //data sent from engine?
case 'End': //remove a round $input = $GLOBALS['HTTP_RAW_POST_DATA'];
if($server->RemoveReference($csid)) { $action = ParseINI::parseValue('Action', $input);
C4Network::SendAnswer(C4Network::CreateAnswer(array('Status' => 'Success'))); $csid = ParseINI::parseValue('CSID', $input);
} $csid = mysql_real_escape_string($csid, $link);
else { $reference = mysql_real_escape_string(strstr($input, '[Reference]'), $link);
C4Network::SendAnswer(C4Network::CreateError('Round end failed.')); $engine_string = ParseINI::parseValue('c4ms_engine', $config);
} if (empty($engine_string) || ParseINI::parseValue('Game', $input) == $engine_string) {
break; switch ($action) {
default: case 'Start': //start a new round
if (!empty($action)) { if (ParseINI::parseValue('LeagueAddress', $reference)) {
C4Network::SendAnswer(C4Network::CreateError('Unknown action.')); C4Network::sendAnswer(C4Network::createError('League not supported!'));
} } else {
else { $csid = $server->addReference($reference);
C4Network::SendAnswer(C4Network::CreateError('No action defined.')); if ($csid) {
} C4Network::sendAnswer(C4Network::createAnswer(array('Status' => 'Success', 'CSID' => $csid)));
break; } else {
} C4Network::sendAnswer(C4Network::createError('Round signup failed. (To many tries?)'));
} }
else { }
C4Network::SendAnswer(C4Network::CreateError('Wrong engine.')); break;
} case 'Update': //update an existing round
} if ($server->updateReference($csid, $reference)) {
else { //list availabe games C4Network::sendAnswer(C4Network::createAnswer(array('Status' => 'Success')));
$list = $server->GetReferenceArray(false); } else {
$message = "[OpenClonk]\nVersion=4,10,0,3\nMOTD=<c 0fff0f>Which is worse: ignorance or apathy? Who knows? Who cares?\n\n"; C4Network::sendAnswer(C4Network::createError('Round update failed.'));
foreach($list as $reference) { }
if(!empty($message)) $message .= "\n\n"; break;
$message .= $reference['data']; case 'End': //remove a round
$message .= 'GameId='.$reference['id']."\n"; if ($server->removeReference($csid)) {
} C4Network::sendAnswer(C4Network::createAnswer(array('Status' => 'Success')));
C4Network::SendAnswer($message); } else {
} C4Network::sendAnswer(C4Network::createError('Round end failed.'));
mysql_close($link); }
} break;
else { default:
C4Network::SendAnswer(C4Network::CreateError('Database error.')); if (!empty($action)) {
} C4Network::sendAnswer(C4Network::createError('Unknown action.'));
} else {
C4Network::sendAnswer(C4Network::createError('No action defined.'));
}
break;
}
} else {
C4Network::sendAnswer(C4Network::createError('Wrong engine, "' . ParseINI::parseValue('Game', $input) . '" expected.'));
}
} else { //list availabe games
if (!isset($_GET['action']) || $_GET['action'] == 'version')
$list = $server->getReferenceArray(false);
$message = '';
$engine = ParseINI::parseValue('c4ms_title_engine', $config);
$platform = isset($_GET['platform']) ? mysql_real_escape_string($_GET['platform'], $link) : 0;
$client_version = isset($_GET['version']) ? mysql_real_escape_string($_GET['version'], $link) : 0;
if (!empty($engine)) {
$message .= '[' . $engine . ']' . PHP_EOL;
if (ParseINI::parseValue('oc_enable_update', $config) == 1) {
if ($platform && $client_version) {
$result = mysql_query('SELECT `new_version` FROM `' . ParseINI::parseValue('mysql_prefix', $config) . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\'');
$row = mysql_fetch_assoc($result);
$version = $row['new_version'];
if ($version) {
$message .= 'Version=' . $version . PHP_EOL;
if (version_compare($client_version, $version) < 0) { //We need to update
$result = mysql_query('SELECT `file` FROM `' . $prefix . 'update` WHERE `old_version` = \'' . $client_version . '\' AND `platform` = \'' . $platform . '\'');
$row = mysql_fetch_assoc($result);
if ($row['file'])
$message .= 'UpdateURL=' . ParseINI::parseValue('oc_update_url', $config) . $row['file'] . PHP_EOL;
}
}
}
}
$motd = ParseINI::parseValue('c4ms_motd', $config);
if (!empty($motd))
$message .= 'MOTD=' . $motd . PHP_EOL;
}
foreach ($list as $reference) {
if (!empty($message))
$message .= PHP_EOL;
$message .= $reference['data'];
$message .= 'GameId=' . $reference['id'] . PHP_EOL;
$message .= 'OfficialServer=false' . PHP_EOL;
}
C4Network::sendAnswer($message);
}
mysql_close($link);
}
else {
C4Network::sendAnswer(C4Network::createError('Database error.'));
}
?> ?>