1<?php
2
3/**
4 * C4Masterserver engine backend
5 *
6 * @package C4Masterserver
7 * @version 1.2.0-en
8 * @author  Benedict Etzel <b.etzel@live.de>
9 * @license http://creativecommons.org/licenses/by/3.0/ CC-BY 3.0
10 */
11//error_reporting(E_ALL); //suppress errors
12
13require_once('include/C4Masterserver.php');
14require_once('include/C4Network.php');
15require_once('include/FloodProtection.php');
16require_once('include/ParseINI.php');
17$C4HostTestIncludeMode = true;
18require_once('include/C4HostTest.php');
19
20$config = file_get_contents('include/config.ini');
21$link = mysql_connect(
22	ParseINI::parseValue('mysql_host', $config),
23	ParseINI::parseValue('mysql_user', $config),
24	ParseINI::parseValue('mysql_password', $config)); //connect to MySQL
25$db = mysql_selectdb(ParseINI::parseValue('mysql_db', $config), $link); //select the database
26
27header('Content-Type: text/plain'); //output as plain text
28
29if ($link && $db) {
30	$prefix = ParseINI::parseValue('mysql_prefix', $config);
31	$server = new C4Masterserver($link, $config);
32	$server->setTimeoutgames(intval(ParseINI::parseValue('c4ms_timeoutgames', $config)));
33	$server->setDeletegames(intval(ParseINI::parseValue('c4ms_deletegames', $config)));
34	$server->setMaxgames(intval(ParseINI::parseValue('c4ms_maxgames', $config)));
35	$protect = new FloodProtection($link, $prefix);
36	$protect->setMaxflood(intval(ParseINI::parseValue('flood_maxrequests', $config)));
37	if ($protect->checkRequest($_SERVER['REMOTE_ADDR'])) { //flood protection
38		C4Network::sendAnswer(C4Network::createError('Flood protection.'));
39		die();
40	}
41	$server->cleanUp(true); //Cleanup old stuff
42	if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'release-file') {
43		try {
44			registerRelease();
45		} catch(Exception $e) {
46			C4Network::sendAnswer(C4Network::createError($e->getMessage()));
47		}
48	} else if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) { //data sent from engine?
49		$input = $GLOBALS['HTTP_RAW_POST_DATA'];
50		$action = ParseINI::parseValue('Action', $input);
51		$csid = ParseINI::parseValue('CSID', $input);
52		$csid = mysql_real_escape_string($csid, $link);
53		$reference = mysql_real_escape_string(strstr($input, '[Reference]'), $link);
54		$engine_string = ParseINI::parseValue('c4ms_engine', $config);
55		if (empty($engine_string) || ParseINI::parseValue('Game', $input) == $engine_string) {
56			switch ($action) {
57			case 'Start': //start a new round
58				if (ParseINI::parseValue('LeagueAddress', $reference)) {
59					C4Network::sendAnswer(C4Network::createError('League not supported!'));
60				} else {
61					$csid = $server->addReference($reference);
62					if ($csid) {
63						$answer = array('Status' => 'Success', 'CSID' => $csid);
64						if(!testHostConn($input))
65							$answer['Message'] = 'Your network failed to pass certain tests. It is unlikely that are you able to host for the public.|To fix that, you need port forwarding in your router.';
66						C4Network::sendAnswer(C4Network::createAnswer($answer));
67						unset($answer);
68					} else {
69						C4Network::sendAnswer(C4Network::createError('Round signup failed. (To many tries?)'));
70					}
71				}
72				break;
73			case 'Update': //update an existing round
74				if ($server->updateReference($csid, $reference)) {
75					C4Network::sendAnswer(C4Network::createAnswer(array('Status' => 'Success')));
76				} else {
77					C4Network::sendAnswer(C4Network::createError('Round update failed.'));
78				}
79				break;
80			case 'End': //remove a round
81				if ($server->removeReference($csid)) {
82					C4Network::sendAnswer(C4Network::createAnswer(array('Status' => 'Success')));
83				} else {
84					C4Network::sendAnswer(C4Network::createError('Round end failed.'));
85				}
86				break;
87			default:
88				if (!empty($action)) {
89					C4Network::sendAnswer(C4Network::createError('Unknown action.'));
90				} else {
91					C4Network::sendAnswer(C4Network::createError('No action defined.'));
92				}
93				break;
94			}
95		} else {
96			C4Network::sendAnswer(C4Network::createError('Wrong engine, "' . ParseINI::parseValue('Game', $input) . '" expected.'));
97		}
98	} else { //list availabe games
99		$list = array();
100		if (!isset($_GET['action']) || (isset($_GET['action']) && $_GET['action'] != 'version')) {
101			$list = $server->getReferenceArray(false);
102		}
103		$message = '';
104		$engine = ParseINI::parseValue('c4ms_title_engine', $config);
105		$platform = isset($_REQUEST['platform']) ? mysql_real_escape_string($_REQUEST['platform'], $link) : 0;
106		$client_version = isset($_REQUEST['version']) ? mysql_real_escape_string($_REQUEST['version'], $link) : 0;
107		if (!empty($engine)) {
108			$message .= '[' . $engine . ']' . PHP_EOL;
109			if (ParseINI::parseValue('oc_enable_update', $config) == 1) {
110				if ($platform && $client_version) {
111					$result = mysql_query('SELECT `new_version` FROM `' . ParseINI::parseValue('mysql_prefix', $config) . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\'');
112					$row = mysql_fetch_assoc($result);
113					$version = $row['new_version'];
114					if ($version) {
115						$message .= 'Version=' . $version . PHP_EOL;
116						// strip build version from client request
117						$n = 0;
118						for($i=0;$i<strlen($client_version);$i++){
119							if($client_version[$i]=='.'){
120								$n++;
121								if($n>=3){
122									break;
123								}
124							}
125						}
126						$client_version = substr($client_version,0,$i);
127						if (version_compare($client_version, $version) < 0) { //We need to update
128							$result = mysql_query('SELECT `file` FROM `' . $prefix . 'update` WHERE `old_version` = \'' . $client_version . '\' AND `platform` = \'' . $platform . '\'');
129							$row = mysql_fetch_assoc($result);
130							if ($row['file'])
131								$message .= 'UpdateURL=' . ParseINI::parseValue('oc_update_url', $config) . $row['file'] . PHP_EOL;
132						}
133					}
134				}
135			}
136			$motd = ParseINI::parseValue('c4ms_motd', $config);
137			if (!empty($motd))
138				$message .= 'MOTD=' . $motd . PHP_EOL;
139		}
140		foreach ($list as $reference) {
141			if (!empty($message))
142				$message .= PHP_EOL;
143			$message .= $reference['data'];
144			$message .= 'GameId=' . $reference['id'] . PHP_EOL;
145			$message .= 'OfficialServer=false' . PHP_EOL;
146		}
147		C4Network::sendAnswer($message);
148	}
149	mysql_close($link);
150}
151else {
152	C4Network::sendAnswer(C4Network::createError('Database error.'));
153}
154
155
156function registerRelease()
157{
158	global $config, $link, $prefix;
159
160	// check request validity
161
162	if (ParseINI::parseValue('oc_enable_update', $config) != 1)
163		throw new Exception('Update disabled on this server.');
164
165	// mandatory parameters
166	if (!isset($_REQUEST['file']))
167		throw new Exception('Missing mandatory parameter "file"');
168
169	if (!isset($_REQUEST['hash']))
170		throw new Exception('Missing mandatory parameter "hash"');
171
172	if (!isset($_REQUEST['new_version']))
173		throw new Exception('Missing mandatory parameter "new_version"');
174
175	if (!isset($_REQUEST['platform']))
176		throw new Exception('Missing mandatory parameter "platform"');
177
178	if (!isset($_REQUEST['hash']))
179		throw new Exception('Missing mandatory parameter "hash"');
180
181	// authorization
182	$absolutefile = ParseINI::parseValue('oc_update_path', $config) . $_REQUEST['file'];
183
184	if (!file_exists($absolutefile))
185		throw new Exception('Specified file "'.$absolutefile.'" not found.');
186
187	$filehash = hash_hmac_file('sha256', $absolutefile, ParseINI::parseValue('oc_update_secret', $config));
188
189	if ($filehash != $_REQUEST['hash'])
190		throw new Exception('Authorization failure: Hash incorrect.');
191
192	// checks done, now update DB
193	$old_version = array();
194	if (isset($_REQUEST['old_version']) && !empty($_REQUEST['old_version']))
195		$old_version = explode(',', mysql_real_escape_string($_REQUEST['old_version'], $link));
196
197	$delete_old_files = false;
198	if (isset($_REQUEST['delete_old_files']) && $_REQUEST['delete_old_files'] == 'yes')
199		$delete_old_files = true;
200
201	$new_version = mysql_real_escape_string($_REQUEST['new_version'], $link);
202	$platform = mysql_real_escape_string($_REQUEST['platform'], $link);
203	$file = mysql_real_escape_string($_REQUEST['file'], $link);
204
205	if (!empty($old_version)) {
206		if ($delete_old_files) {
207			$result = mysql_query('SELECT `file` FROM `' . $prefix . 'update` WHERE `new_version` != \'' . $new_version . '\' AND `old_version` != \'\' AND `platform` = \'' . $platform . '\'');
208			while (($row = mysql_fetch_assoc($result)) != false) {
209				unlink(ParseINI::parseValue('oc_update_path', $config) . $row['file']);
210			}
211		}
212		mysql_query('DELETE FROM `' . $prefix . 'update` WHERE `new_version` != \'' . $new_version . '\' AND `old_version` != \'\' AND `platform` = \'' . $platform . '\'');
213		foreach ($old_version as $version) {
214			mysql_query('INSERT INTO `' . $prefix . 'update` (`old_version`, `new_version`, `platform`, `file`) VALUES (\'' . $version . '\', \'' . $new_version . '\', \'' . $platform . '\', \'' . $file . '\')');
215		}
216	} else {
217		if ($delete_old_files) {
218			$row = mysql_fetch_assoc(mysql_query('SELECT `file` FROM `' . $prefix . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\''));
219			unlink(ParseINI::parseValue('oc_update_path', $config) . $row['file']);
220		}
221		mysql_query('DELETE FROM `' . $prefix . 'update` WHERE `old_version` = \'\' AND `platform` = \'' . $platform . '\'');
222		mysql_query('INSERT INTO `' . $prefix . 'update` (`old_version`, `new_version`, `platform`, `file`) VALUES (\'\', \'' . $new_version . '\', \'' . $platform . '\', \'' . $file . '\')');
223	}
224}
225
226?>
227