document = new DomDocument('1.0', 'utf-8'); $this->outputMode = "xml"; } function maintenance($maintenance) { $this->data = new data_node('Maintenance'); $this->data->addContents(new data_leaf('Until', strftime("%Y-%m-%d %H:%M:%S", $maintenance['until']))); $this->data->addContents(new data_leaf('Current', gmstrftime("%Y-%m-%d %H:%M:%S"))); $this->data->addContents(new data_leaf('Reason', $maintenance['reason'])); $this->rawOutput($this->genOutput('xml')); } function displayFatalError($code, $i, $i2) { $this->data = new data_node('FatalError'); $this->data->setAttribute('code', $code); $this->data->addContents(new data_leaf('Text', $i)); return $this->genOutput('xml'); } private function loginFailed($code) { $this->data = new data_node('Failed'); $this->data->setAttribute('code', $code); $this->rawOutput($this->genOutput('xml')); } private function kicked($reason) { $this->data = new data_node('Kicked'); $this->data->addContents(new data_leaf('Reason', $reason)); $this->rawOutput($this->genOutput('xml')); } function initSession() { // Check for "single-shot" request if (input::$input['__s'] == 1) { $_SESSION = array(); return; } // FIXME: handle session, but why bother doing it when the whole thing will be rewritten? } function checkAuth() { // Check authentication directly in "single-shot" mode if (input::$input['__s'] == 1) { $this->singleShotAuth(input::$input['__l'], input::$input['__p']); $this->outputMode = "lw"; return; } // FIXME: handle authentication, but why bother doing it when the whole thing will be rewritten? } private function singleShotAuth($login, $password) { // Check the account's login and password if (!$this->checkAccountAuth($login, $password)) { sleep(5); $this->loginFailed(0); } // Make sure the account is in a valid state $q = dbQuery("SELECT status,reason FROM account WHERE id={$_SESSION['userid']}"); if (!$q || dbCount($q) != 1) { $this->loginFailed(1); } list($status,$reason) = dbFetchArray($q); if ($status == 'KICKED') { $this->kicked($reason); } elseif ($status == 'QUIT' || $status == 'INAC') { $this->loginFailed(2); } elseif ($status == 'NEW') { $this->loginFailed(3); } $_SESSION['authok'] = true; if (!$this->checkVersionRegistration()) { $this->loginFailed(4); } $this->singleShotLog(); } private function checkAccountAuth($l, $p) { $l1 = addslashes($l); $p1 = addslashes($p); $q = "SELECT id,name,password FROM account WHERE lower(name)=lower('$l1')"; $qr = dbQuery($q); if (!$qr || dbCount($qr) != 1) { l::info("Single-shot account authentication failed: login '".urlencode($l)."' not found"); if ($qr) { l::debug("Query returned " . dbCount($qr) . " row(s)", LOG_DEBUG); } return false; } list($uid,$l2,$pw) = dbFetchArray($qr); if ($p != $pw) { l::info("Single-shot account authentication failed: login '" . urlencode($l) . "' used invalid password"); l::debug("User ID: $uid ; real user name: $l2"); return false; } $_SESSION['login'] = $l2; $_SESSION['userid'] = $uid; return true; } private function checkVersionRegistration() { if (input::$path == "main") { return true; } $game = config::getGame(input::$path); $lib = $game->getLib(); $pid = $lib->call("doesUserPlay", $_SESSION['userid']); if (is_null($pid)) { return false; } if (!is_array($_SESSION["{$game->name}_data"])) { $_SESSION["{$game->name}_data"] = array("player" => $pid); } return true; } private function singleShotLog() { $uid = $_SESSION['userid']; $q = dbQuery("SELECT id FROM web_session WHERE account = $uid"); if (!($q && dbCount($q))) { $in = time(); $out = $in + 1; $q = dbQuery("UPDATE account SET last_login=$in,last_logout=$out WHERE id=$uid"); } dbQuery("INSERT INTO account_log(account,ip_addr,action,t) VALUES ($uid,'AUTO','IN',unix_timestamp(now()) - 1)"); dbQuery("INSERT INTO account_log(account,ip_addr,action) VALUES ($uid,'AUTO','OUT')"); } function handleInput() { $data = handler::$h->xml(input::$input); if (!($data instanceof data_gen)) { l::fatal(18, "In XML handler for " . input::$path . "/" . input::$page); } $this->data = $data; } function initRPC() { /*NO RPC*/ } function outputData() { $data = $this->genOutput($this->outputMode); if (input::$IE || input::$safari || tracking::$disabled) { $this->rawOutput($data); } else { $this->cachedOutput($data); } } private function cachedOutput($data) { // Generate an XML resource from the data addRawResource('xml', $data); $resId = storeResource("xml", 21600, false); $xmlId = md5($_SERVER['REQUEST_URI']) . ":$resId"; // Check the tracking cookie for the required contents if (!is_array(tracking::$data['xmlId'])) { tracking::$data['xmlId'] = array(); } if (!isset(tracking::$data['xmlId'][$xmlId])) { tracking::$data['xmlId'][$xmlId] = time(); } // Send the page's header $time = tracking::$data['xmlId'][$xmlId]; $lastModified = substr(date('r', $time), 0, -5).'GMT'; $etag = '"'.md5($lastModified).'"'; header("Content-Type: text/xml; charset=utf-8"); header("Last-Modified: $lastModified GMT"); header("ETag: $etag"); header("Cache-Control: no-cache, must-revalidate"); // Sends either a 304 reply or the data depending on the browser's will $ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false; $ifNoneMatch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false; if (($ifNoneMatch || $ifModifiedSince) && (!$ifNoneMatch || $ifNoneMatch == $etag) && (!$ifModifiedSince || $ifModifiedSince != $lastModified)) { header('HTTP/1.0 304 Not Modified'); } else { endRequest(false); echo $data; exit(0); } } private function rawOutput($data) { header("Content-Type: text/xml; charset=utf-8"); header("Expires: Thu, 19 Feb 1981 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); // Send the data directly endRequest(false); echo $data; exit(0); } private function genOutput($mode) { if ($mode == 'xml') { $data = $this->data->toXML($this->document); } else { $data = $this->data->toLWData($this->document); } $this->document->appendChild($data); return $this->document->saveXML(); } } ?>