<?php error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING); if (isset($_GET['viewsource'])) { echo("<table><tr><td nowrap>"); show_source("savequests.php"); die("</td></tr></table>"); } header('Content-Type: text/xml'); $username = addslashes($_POST['username']); $password = addslashes($_POST['password']); if (strlen($username) < 5 || strlen($password) < 5) die('<error reason="Username and Password must be at least 5 characters long" />'); if (strlen($username) > 30 || strlen($password) > 30) die('<error reason="Username and Password cannot be more than 30 characters long" />'); $questxml = $_POST['questxml']; $lastmodified = addslashes($_POST['lastmodified']); //Date will be in GMT with the format yyyy-mm-dd hh:mm:ss $acctchars = addslashes($_POST['acctchars']); $gmtoffset = addslashes($_POST['gmtoffset']); if (strpos($questxml, "<Quests") === false) die('<error reason="Invalid Quests XML file" />'); $currentcharacter = addslashes($_POST['currentcharacter']); $currentworld = addslashes($_POST['currentworld']); if (isset($_POST['compare_merge'])) $compare_merge = strtoupper(addslashes($_POST['compare_merge'])); //NONE, COMPARE, or MERGE else $compare_merge = 'NONE'; if (isset($_POST['uploadct']) && $_POST['uploadct'] <> '') { $uploadct = addslashes($_POST['uploadct']); $check_uploadct = (bool)($uploadct >= 0); //Plugin will send -1 if checking should not be perfomed } else $check_uploadct = false; if (isset($_POST['currenttime']) && $_POST['currenttime'] <> '') { $client_timestamp = strtotime(addslashes($_POST['currenttime']) . '+0000'); // Sent in GMT if ($client_timestamp === -1) // Invalid time $client_timestamp = time(); } else $client_timestamp = time(); $client_time = gmdate('Y-m-d H:i:s', $client_timestamp); $restoredquests = ""; // Connection to mysql is done in sql_config.php, which is included before this file if (defined('MYSQL_CONNECTED')) { if ($result = mysql_query("SELECT * FROM QuestTimer_UserQuests WHERE username='$username'")) { if ($data = mysql_fetch_array($result)) { if ($compare_merge != 'NONE') { $database_questxml = gzuncompress($data['questxml']) or die('<error reason="Failed to uncompress Quest XML from database" />'); } if ($data['password'] == stripslashes($password)) { if ($check_uploadct && $uploadct < $data['uploadct']) { echo('<OldFile/>'); } elseif ($compare_merge == 'COMPARE' && !check_otherchars($database_questxml, $questxml, false)) { echo('<OtherCharMismatch/>'); } else { $merged = ($compare_merge == 'MERGE' && !check_otherchars($database_questxml, $questxml, true)); if ($merged) $lastmodified = $client_time; $uploadct = $data['uploadct'] + 1; $questxml_compressed = gzcompress($questxml) or die('<error reason="Failed to compress Quest XML to store in database" />'); $compressed_len = strlen($questxml_compressed); $questxml_compressed = addslashes($questxml_compressed); if ($compressed_len > 65535) { echo('<error reason="Your quest file is too large, even after GZIP compression. The file must be smaller than 64 KB; yours is ' . round($compressed_len / 1024, 2) . ' KB after compression" />'); echo('<!-- Note: To reduce the size, remove some quests or set "Time Up" quests to "Not Completed" -->'); } elseif (mysql_query("UPDATE QuestTimer_UserQuests SET lastmodified='$lastmodified', questxml='$questxml_compressed', acctchars='$acctchars', gmtoffset='$gmtoffset', lastuploaded='" . gmdate('Y-m-d H:i:s') . "', uploadct='$uploadct' WHERE username='$username'")) { if ($merged) { // Return the quest XML so the plugin can update it echo("<Merged uploadct='$uploadct' restoredquests='" . htmlspecialchars($restoredquests) . "'>$questxml</Merged>"); } else { echo("<Success uploadct='$uploadct'/>"); } } else echo('<error reason="Failed to update record in database: ' . mysql_error() . '" />'); } } else echo('<error reason="Password does not match Username" />'); } else //User does not exist { $questxml_compressed = gzcompress($questxml) or die('<error reason="Failed to compress Quest XML to store in database" />'); //die('<error reason="Error">' . base64_encode($questxml_compressed) . '</error>'); $questxml_compressed = addslashes($questxml_compressed); if (mysql_query("INSERT INTO QuestTimer_UserQuests (username,password,lastmodified,lastuploaded,uploadct,acctchars,gmtoffset,questxml) VALUES ('$username','$password','$lastmodified','" . gmdate('Y-m-d H:i:s') . "','1','$acctchars','$gmtoffset','$questxml_compressed')")) echo("<Success uploadct='1'/> <!-- Note: Username " . htmlspecialchars(stripslashes($username)) . " did not exist and was created with the supplied password -->"); else echo('<error reason="Failed to create new record in database: ' . mysql_error() . '" />'); } } else echo('<error reason="SQL Query error: ' . mysql_error() . '" />'); } else echo('<error reason="Failed to connect to database" />');
/*Create Table: CREATE TABLE `QuestTimer_UserQuests` ( `username` varchar(30) NOT NULL default '', `password` varchar(30) NOT NULL default '', `lastmodified` datetime NOT NULL default '0000-00-00 00:00:00', `lastuploaded` datetime NOT NULL default '0000-00-00 00:00:00', `uploadct` int(11) NOT NULL default '0', `acctchars` text NOT NULL, `gmtoffset` varchar(10) NOT NULL default '-0500', `questxml` text NOT NULL, PRIMARY KEY (`username`,`password`) ) TYPE=MyISAM; */ function check_otherchars(&$database_xml, &$uploaded_xml, $do_merge) /* if $do_merge is TRUE, merge the two XMLs; otherwise just check for differences returns TRUE if info for characters other than $currentcharacter matches between XMLs *** THIS FUNCTION USES DOM, WHICH IS ONLY AVAILABLE IN PHP 5 *** If you're using PHP 4, you'll have to convert to DOMXML. See http://www.php.net for more info. */ { global $currentcharacter, $currentworld, $restoredquests; $cur_char_world = strtolower("$currentcharacter [$currentworld]"); $xmlOldQuests = DOMDocument::loadXML($database_xml); $xmlNewQuests = DOMDocument::loadXML($uploaded_xml); if (!is_object($xmlOldQuests)) { echo("<!-- Note: Server failed to parse quests xml in database. If you see this error often, contact me. -->"); return true; } if (!is_object($xmlNewQuests)) { die('<error reason="Failed to parse the uploaded quests xml. Disable character info match checking to upload anyways."/>'); } $retval = true; foreach ($xmlOldQuests->documentElement->getElementsByTagName('Quest') as $OldQuest) { $found_quest = false; foreach ($xmlNewQuests->documentElement->getElementsByTagName('Quest') as $NewQuest) { if (strtolower($OldQuest->getAttribute('QuestName')) == strtolower($NewQuest->getAttribute('QuestName'))) { foreach ($OldQuest->getElementsByTagName('Character') as $OldChar) { // Skip current character or ones whose timer has already expired if (char_world($OldChar) == $cur_char_world || timer_expired($OldQuest, $OldChar)) continue; $found_char = false; foreach ($NewQuest->getElementsByTagName('Character') as $NewChar) { if (char_world($OldChar) == char_world($NewChar)) { $old_completed = strtotime($OldChar->getAttribute('Completed')); $new_completed = strtotime($NewChar->getAttribute('Completed')); if ($old_completed !== -1 && $new_completed !== -1 && $old_completed > $new_completed) { if (!$do_merge) return false; $retval = false; $NewChar->setAttribute('Completed', $OldChar->getAttribute('Completed')); } $found_char = true; break; } // if (char_world($OldChar) == char_world($NewChar)) } // foreach (... as $NewChar) if (!$found_char) { if (!$do_merge) return false; $retval = false; $NewQuest->appendChild($xmlNewQuests->importNode($OldChar, true)); } } // foreach (... as $OldChar) $found_quest = true; break; } // if ($OldQuest->getAttribute('QuestName') == $NewQuest->getAttribute('QuestName')) } // foreach (... as $NewQuest) if (!$found_quest) { $quest_added = false; foreach ($OldQuest->getElementsByTagName('Character') as $OldChar) { // Skip current character or ones whose timer has already expired if (char_world($OldChar) == $cur_char_world || timer_expired($OldQuest, $OldChar)) continue; if (!$do_merge) return false; $retval = false; if (!$quest_added) { // Append a copy of the quest node with all child nodes intact $NewQuest = $xmlNewQuests->documentElement->appendChild($xmlNewQuests->importNode($OldQuest, true)); // Remove all of the Character nodes (but leave the Note nodes intact) // This is so we only have the Characters whose timers haven't expired while ($NewQuest->getElementsByTagName('Character')->length > 0) { $NewChar = $NewQuest->getElementsByTagName('Character')->item(0); $NewQuest->removeChild($NewChar); } $quest_added = true; $restoredquests[] = $NewQuest->getAttribute('QuestName'); } $NewQuest->appendChild($xmlNewQuests->importNode($OldChar, true)); } // foreach (... as $OldChar) } // if (!$found_quest) } // foreach (... as $OldQuest) if (is_array($restoredquests)) { $restoredquests = join($restoredquests, ', '); } if ($do_merge && $retval == false) { // Only the document element, not the processing instructions like < ?xml version="1.0" ? > $uploaded_xml = $xmlNewQuests->saveXML($xmlNewQuests->documentElement); } return $retval; } function char_world(&$char_node) { return strtolower($char_node->getAttribute('Name') . ' [' . $char_node->getAttribute('Server') . ']'); } function timer_expired(&$quest_node, &$char_node) { global $gmtoffset, $client_timestamp; $mins = $quest_node->getAttribute('Minutes'); $hours = $quest_node->getAttribute('Hours'); $days = $quest_node->getAttribute('Days'); $quest_duration = 60 * ($mins + 60 * ($hours + 24 * $days)); $completed = strtotime($char_node->getAttribute('Completed') . $gmtoffset); return ($client_timestamp > ($completed + $quest_duration)); } ?>
|