public function parse($path) { $mpq = new MPQFile($path, true, false); $init = $mpq->getState(); if (!$init) { return false; } $r = $mpq->parseReplay(); if (!$r) { return false; } $this->r_infos['version'] = $mpq->getVersionString(); $this->r_infos['realm'] = $r->getRealm(); $this->r_infos['speed'] = $r->getGameSpeed(); $this->r_infos['winner_known'] = $r->isWinnerKnown(); $this->r_infos['type'] = $r->getTeamSize(); $this->r_infos['length'] = $r->getGameLength(); $this->r_infos['real_length'] = (int) ($this->r_infos['length'] * 60) / 83.5; $this->r_infos['map'] = $r->getMapName(); $this->r_infos['map_hash'] = $r->getMapHash(); $this->r_infos['players'] = $r->getPlayers(); foreach ($this->r_infos['players'] as $k => &$player) { if ($player['isObs']) { $this->r_infos['obs'][] = $this->r_infos['players'][$k]; unset($this->r_infos['players'][$k]); continue; } $player['army'] = $player['race']; $player['bnet_id'] = (int) $player['uid']; } $this->computeAPM(); $this->_computeMessages($r); $this->_computeWinner(); return true; }
private function parseDocumentHeader($string) { $numByte = 44; // skip header and unknown stuff $numDeps = MPQFile::readByte($string, $numByte); // uncertain that this is the number of dependencies, might also be uint32 if it is $numByte += 3; while ($numDeps > 0) { while (MPQFile::readByte($string, $numByte) !== 0) { } $numDeps--; } $numAttribs = MPQFile::readUInt32($string, $numByte); $attribs = array(); while ($numAttribs > 0) { $keyLen = MPQFile::readUInt16($string, $numByte); $key = MPQFile::readBytes($string, $numByte, $keyLen); $numByte += 4; // always seems to be followed by ascii SUne $valueLen = MPQFile::readUInt16($string, $numByte); $value = MPQFile::readBytes($string, $numByte, $valueLen); $attribs[$key] = $value; $numAttribs--; } $this->author = $attribs["DocInfo/Author"]; $this->mapName = $attribs["DocInfo/Name"]; $this->description = $attribs["DocInfo/DescLong"]; $this->shortDescription = $attribs["DocInfo/DescShort"]; }
function test_file($file) { echo "Testing {$file} \n"; $mpq = new MPQFile($file); $rep = $mpq->parseReplay(); if (!$rep) { echo "Parse error!"; return; } $new = $rep->jsonify(); if (file_exists($file . '.parsed')) { $old = file_get_contents($file . '.parsed'); $diff = diff($old, $new); if ($diff != -1) { echo $file . ': position ' . $diff . ' old: >>' . substr($old, $diff - 5, 10) . '<< new: >>' . substr($new, $diff - 5, 10) . "<< "; file_put_contents($file . '.new.parsed', $new); echo "New content saved as " . $file . ".new.parsed\n"; //printDiff($old, $new); } } else { file_put_contents($file . '.parsed', $new); echo "Content saved as {$file}.parsed\n"; } }
$err = true; } if ($error == UPLOAD_ERR_NO_FILE) { $text .= "Error: No file was selected for uploading.<br />"; $err = true; } if (!is_uploaded_file($tmpname)) { $text .= "Error: Uploaded filename doesn't point to an uploaded file.<br />"; $err = true; } if ($err !== true) { if (class_exists("MPQFile") || (include './include/replays/mpqfile.php')) { $start = microtime_float(); $parseDurationString = ""; $debug = 0; $a = new MPQFile($tmpname, true, $debug); $init = $a->getState(); if ($init == false) { $text .= "Error parsing uploaded file, make sure it is a valid MPQ archive!<br />\n"; } else { if ($a->getFileType() == "SC2replay") { $b = $a->parseReplay(); $parseDurationString .= sprintf("Parsed replay in %d ms.<br />\n", (microtime_float() - $start) * 1000); $players = $b->getPlayers(); $recorder = $b->getRecorder(); $error_str = ''; if ($event_id) { $event = new Event($event_id); $match = new Match(); // Check if replay->TeamSize == event->MatchType if ($b->getTeamSize() != $event->getField('MatchType')) {
public function addFakeObserver($obsName) { return false; // this function does not work currently so DO NOT USE! if (!$this->init || $this->getFileSize("replay.initData") == 0) { return false; } $string = $this->readFile("replay.initData"); $numByte = 0; $numPlayers = MPQFile::readByte($string, $numByte); $playerAdded = false; $playerId = 0; for ($i = 1; $i <= $numPlayers; $i++) { $nickLen = MPQFile::readByte($string, $numByte); if ($nickLen > 0) { $numByte += $nickLen; $numByte += 5; } elseif (!$playerAdded) { // first empty slot $playerAdded = true; $numByte--; if ($i == $numPlayers) { $len = 5; } else { $len = 6; } // add the player to the initdata file $obsNameLength = strlen($obsName); $repString = chr($obsNameLength) . $obsName . str_repeat(chr(0), 5); $newData = substr($string, 0, $numByte) . $repString . substr($string, $numByte - $len + strlen($repString)); $numByte += strlen($repString); //$this->replaceFile("replay.initData", $newData); $playerId = $i; $string = $newData; // skip the next null part because it is 1 byte shorter than normal if ($i < $numPlayers) { $i++; $numByte += 4; } } else { $numByte += 5; } } if ($this->debug) { $this->debug(sprintf("Got past first player loop, counter = {$i}, numbyte: %04X", $numByte)); } if ($playerId == 0) { return false; } $numByte += 25; $accountIdentifierLength = MPQFile::readByte($string, $numByte); if ($accountIdentifierLength > 0) { $accountIdentifier = MPQFile::readBytes($string, $numByte, $accountIdentifierLength); } $numByte += 684; // length seems to be fixed, data seems to vary at least based on number of players while (true) { $str = MPQFile::readBytes($string, $numByte, 4); if ($str != 's2ma') { $numByte -= 4; break; } $numByte += 2; // 0x00 0x00 $realm = MPQFile::readBytes($string, $numByte, 2); $this->realm = $realm; $numByte += 32; } // start of variable length data portion $numByte += 2; $numPlayers = MPQFile::readByte($string, $numByte); // need to increment numplayers by 1 $string = substr_replace($string, pack("c", $numPlayers + 1), $numByte - 1, 1); $numByte += 4; for ($i = 1; $i <= $numPlayers; $i++) { $firstByte = MPQFile::readByte($string, $numByte); $secondByte = MPQFile::readByte($string, $numByte); if ($this->debug) { $this->debug(sprintf("Function addFakeObserver: numplayer: %d, first byte: %02X, second byte: %02X", $i, $firstByte, $secondByte)); } switch ($firstByte) { case 0xca: switch ($secondByte) { case 0x20: // player $numByte += 20; break; case 0x28: // player $numByte += 24; break; case 0x4: case 0x2: // spectator // spectator case 0x0: // computer $numByte += 4; break; } break; case 0xc2: switch ($secondByte) { case 0x4: $tmp = MPQFile::readByte($string, $numByte); if ($tmp == 0x5) { $numByte += 4; } $numByte += 20; break; case 0x24: case 0x44: $numByte += 5; break; } break; default: if ($this->debug) { $this->debug(sprintf("Function addFakeObserver: Unknown byte at byte offset %08X, got %02X", $numByte, $firstByte)); } return false; } } // insert join game event and initial camera event for the newly created player $string = $this->readFile("replay.game.events"); $string = substr_replace($string, pack("c3", 0, $playerId, 0xb), 0, 0); $tmpByte = $i * 3 + 5; $camerastring = pack("c2", 0, 0x60 | $playerId) . MPQFile::readBytes($string, $tmpByte, 11); $string = substr_replace($string, $camerastring, $tmpByte, 0); $this->replaceFile("replay.game.events", $string); return $playerId; }
static function parseTimeStamp($string, &$numByte) { $one = MPQFile::readByte($string, $numByte); if (($one & 3) > 0) { // check if value is two bytes or more $two = MPQFile::readByte($string, $numByte); $two = $one >> 2 << 8 | $two; if (($one & 3) >= 2) { $tmp = MPQFile::readByte($string, $numByte); $two = $two << 8 | $tmp; if (($one & 3) == 3) { $tmp = MPQFile::readByte($string, $numByte); $two = $two << 8 | $tmp; } } return $two; } return $one >> 2; }
echo "Error: Uploaded filename doesn't point to an uploaded file.<br />"; $err = true; } if ($err !== true) { if ($_POST['debug'] == 1) { error_reporting(-1); } if (class_exists("MPQFile") || (include 'mpqfile.php')) { $start = microtime_float(); $parseDurationString = ""; $debug = 0; if ($_POST['debug'] == 1 || $_POST['test'] == 1) { echo sprintf("<b>Debugging is on.</b><br />\n"); $debug = 2; } $a = new MPQFile($tmpname, true, $debug); $init = $a->getState(); if (isset($_POST['test']) && $_POST['test'] == 1) { if (class_exists("SC2Replay") || (include 'sc2replay.php')) { //$bool = $a->insertChatLogMessage("testing testing", "testguy", 1); //$bool = $a->insertChatLogMessage("testing 2", 1, 5); //$a->saveAs("testfile.SC2Replay", true); //$a = new MPQFile("testfile.SC2Replay", true, 2); $byte = 0; $b = new SC2Replay($a); $b->setDebug(true); $tmp = $b->parseDetailsValue($a->readFile("replay.details"), $byte); echo "<pre>"; var_dump($tmp); echo "</pre>"; die;
static function initCryptTable() { if (!self::$cryptTable) { self::$cryptTable = array(); } $seed = 0x100001; $index1 = 0; $index2 = 0; for ($index1 = 0; $index1 < 0x100; $index1++) { for ($index2 = $index1, $i = 0; $i < 5; $i++, $index2 += 0x100) { $seed = uPlus($seed * 125, 3) % 0x2aaaab; $temp1 = ($seed & 0xffff) << 0x10; $seed = uPlus($seed * 125, 3) % 0x2aaaab; $temp2 = $seed & 0xffff; self::$cryptTable[$index2] = $temp1 | $temp2; } } }