1
0
mirror of https://github.com/Rogiel/php-mpq synced 2025-12-06 08:23:05 +00:00

2 Commits
0.2.1 ... 0.2.3

6 changed files with 60 additions and 42 deletions

View File

@@ -49,7 +49,7 @@ class DeflateCompression implements Compression {
*/ */
public function decompress($data, $length) { public function decompress($data, $length) {
$output = @gzinflate(substr($data, 0, $length), $length); $output = @gzinflate(substr($data, 0, $length), $length);
if(!is_string($output)) { if($output === false) {
throw new InvalidInputDataException('The decompression input data is invalid.', $output); throw new InvalidInputDataException('The decompression input data is invalid.', $output);
} }
return $output; return $output;

View File

@@ -42,19 +42,18 @@ abstract class BaseHashing implements Hashing {
public function hash($string) { public function hash($string) {
$seed1 = 0x7FED7FED; $seed1 = 0x7FED7FED;
$seed2 = ((0xEEEE << 16) | 0xEEEE); $seed2 = 0xEEEEEEEE;
$strLen = strlen($string); $strLen = strlen($string);
for ($i = 0;$i < $strLen;$i++) { for ($i = 0;$i < $strLen;$i++) {
$next = ord(strtoupper(substr($string, $i, 1))); $next = ord(strtoupper(substr($string, $i, 1)));
$seed1 = CryptoUtils::$cryptTable[($this->hashType << 8) + $next] ^ (CryptoUtils::uPlus($seed1,$seed2)); $seed1 = CryptoUtils::$cryptTable[($this->hashType << 8) + $next] ^ (CryptoUtils::uPlus($seed1,$seed2)) & 0xFFFFFFFF;
$seed2 = CryptoUtils::uPlus(CryptoUtils::uPlus(CryptoUtils::uPlus(CryptoUtils::uPlus($next,$seed1),$seed2),$seed2 << 5),3); $seed2 = CryptoUtils::uPlus(CryptoUtils::uPlus(CryptoUtils::uPlus(CryptoUtils::uPlus($next,$seed1),$seed2),$seed2 << 5),3) & 0xFFFFFFFF;
} }
return $seed1; return $seed1;
} }
// function that adds up two integers without allowing them to overflow to floats // function that adds up two integers without allowing them to overflow to floats
private function uPlus($o1, $o2) { private function uPlus($o1, $o2) {
$o1h = ($o1 >> 16) & 0xFFFF; $o1h = ($o1 >> 16) & 0xFFFF;

View File

@@ -81,6 +81,10 @@ class MPQFile {
$this->stream = $stream; $this->stream = $stream;
} }
function __destruct() {
$this->stream->close();
}
// ----------------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------------
public function isParsed() { public function isParsed() {
@@ -98,9 +102,10 @@ class MPQFile {
if($signature == "MPQ27") { if($signature == "MPQ27") {
$this->userData = UserData::parse($parser); $this->userData = UserData::parse($parser);
$this->stream->seek($this->getUserDataOffset()); $this->stream->seek($this->getUserDataOffset());
$signature = $this->parseSignature($parser);
} }
$signature = $this->parseSignature($parser);
if($signature == "MPQ26") { if($signature == "MPQ26") {
$this->header = Header::parse($parser); $this->header = Header::parse($parser);
} }
@@ -130,13 +135,14 @@ class MPQFile {
$parser->seek($this->getUserDataOffset() + $this->getHeader()->getBlockTablePos()); $parser->seek($this->getUserDataOffset() + $this->getHeader()->getBlockTablePos());
$blocks = array(); $blocks = array();
$offsetFix = 0; // $offsetFix = 0;
for($i = 0; $i<$this->getHeader()->getBlockTableSize(); $i++) { for($i = 0; $i<$this->getHeader()->getBlockTableSize(); $i++) {
$block = $blocks[$i - $offsetFix] = Block::parse($parser); $block = $blocks[$i] = Block::parse($parser);
if($block->getSize() == 0) { // if($block->getSize() == 0) {
$offsetFix++; // $offsetFix++;
} // }
} }
return new BlockTable($blocks); return new BlockTable($blocks);
} }
@@ -151,7 +157,7 @@ class MPQFile {
// ----------------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------------
private function getUserDataOffset() { public function getUserDataOffset() {
$userData = $this->getUserData(); $userData = $this->getUserData();
if($userData === null) { if($userData === null) {
return 0; return 0;
@@ -184,6 +190,7 @@ class MPQFile {
if($hash == NULL) { if($hash == NULL) {
return NULL; return NULL;
} }
return $this->getBlockTable()->getBlock($hash->getBlockIndex()); return $this->getBlockTable()->getBlock($hash->getBlockIndex());
} }
@@ -199,25 +206,14 @@ class MPQFile {
$sectors = array(); $sectors = array();
if($block->isChecksumed() || !$block->isSingleUnit()) { if($block->isChecksumed() || !$block->isSingleUnit()) {
$blockSize = $block->getCompressedSize(); $blockSize = 512 * (1 << $this->getHeader()->getBlockSize());
$fileSize = $block->getSize(); $fileSize = $block->getSize();
print_r($this->getBlockTable()->getBlocks());
// print_r($block);
// echo $block->isExisting() ? "true" : "false";
// echo "\n";
//
// echo $fileSize."\n";
// echo $this->getHeader()->getBlockSize()."\n";
for ($i = $fileSize; $i > 0; $i -= $blockSize) { for ($i = $fileSize; $i > 0; $i -= $blockSize) {
echo $i;
$sectors[] = $parser->readUInt32(); $sectors[] = $parser->readUInt32();
$blockSize -= 4; $blockSize -= 4;
} }
print_r($sectors); $sectors[] = $parser->readUInt32();
// $sectors[] = $parser->readUInt32();
} else { } else {
$sectors = array( $sectors = array(
0, 0,
@@ -268,4 +264,4 @@ class MPQFile {
return new MPQFile(new MemoryStream($string)); return new MPQFile(new MemoryStream($string));
} }
} }

View File

@@ -35,6 +35,7 @@ use Rogiel\MPQ\Exception\Compression\CompressionException;
use Rogiel\MPQ\Metadata\Block; use Rogiel\MPQ\Metadata\Block;
use Rogiel\MPQ\MPQFile; use Rogiel\MPQ\MPQFile;
use Rogiel\MPQ\Stream\CompressedStream; use Rogiel\MPQ\Stream\CompressedStream;
use Rogiel\MPQ\Stream\MemoryStream;
use Rogiel\MPQ\Stream\Parser\BinaryStreamParser; use Rogiel\MPQ\Stream\Parser\BinaryStreamParser;
use Rogiel\MPQ\Stream\Stream; use Rogiel\MPQ\Stream\Stream;
@@ -109,7 +110,7 @@ class BlockStream implements Stream {
} }
public function readBytes($bytes) { public function readBytes($bytes) {
if($this->eof()) { if($this->eof()) {
return false; return false;
} }
if(($this->position + $bytes) > $this->block->getSize()) { if(($this->position + $bytes) > $this->block->getSize()) {
@@ -119,7 +120,11 @@ class BlockStream implements Stream {
if($this->buffer === NULL) { if($this->buffer === NULL) {
$this->buffer = $this->readSector($this->currentSector); $this->buffer = $this->readSector($this->currentSector);
$this->positionInSector = 0; $this->positionInSector = 0;
} else if($this->positionInSector >= strlen($this->buffer)) { } else if($this->positionInSector >= strlen($this->buffer)) {
if(!isset($this->sectors[$this->currentSector->getIndex() + 1])) {
return false;
}
$this->currentSector = $this->sectors[$this->currentSector->getIndex() + 1]; $this->currentSector = $this->sectors[$this->currentSector->getIndex() + 1];
$this->buffer = $this->readSector($this->currentSector); $this->buffer = $this->readSector($this->currentSector);
$this->positionInSector = 0; $this->positionInSector = 0;
@@ -157,23 +162,28 @@ class BlockStream implements Stream {
// ----------------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------------
private function readSector(Sector $sector) { private function readSector(Sector $sector) {
$this->stream->seek($this->file->getUserData()->getHeaderOffset() $this->stream->seek($this->file->getUserDataOffset()
+ $this->block->getFilePos() + $this->block->getFilePos()
+ $sector->getStart()); + $sector->getStart());
$compressedStream = $this->createCompressedStream(); $compressedStream = $this->createCompressedStream($sector);
return $compressedStream->readBytes($sector->getLength()); return $compressedStream->readBytes($this->block->getSize());
} }
private function createCompressedStream() { private function createCompressedStream(Sector $sector) {
$stream = $this->stream; $stream = $this->stream;
if($this->block->isCompressed() && $this->block->getSize() > $this->block->getCompressedSize()) { if($this->block->isCompressed() && $this->block->getSize() > $this->block->getCompressedSize()) {
$parser = new BinaryStreamParser($this->stream); $parser = new BinaryStreamParser($this->stream);
$compressionType = $parser->readByte(); $compressionType = $parser->readByte();
switch ($compressionType) { switch ($compressionType) {
case 0x00: return $stream; case 0x00: return $stream;
case 0x02: return new CompressedStream($stream, new DeflateCompression()); case 0x02: {
$len = $parser->readUInt16();
$blockData = $stream->readBytes($len);
return new MemoryStream(gzinflate($blockData));
}
// case 0x02: return new CompressedStream($stream, new DeflateCompression());
case 0x10: return new CompressedStream($stream, new BZIPCompression()); case 0x10: return new CompressedStream($stream, new BZIPCompression());
default: default:
throw new CompressionException(sprintf('Invalid compression format: %s', $compressionType)); throw new CompressionException(sprintf('Invalid compression format: %s', $compressionType));

View File

@@ -40,14 +40,22 @@ class FileStream implements Stream {
$this->handle = fopen($file, 'r'); $this->handle = fopen($file, 'r');
} }
public function __clone() {
$this->handle = fopen($this->file, 'r');
}
function __destruct() {
$this->close();
}
// ----------------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------------
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close() { public function close() {
fclose($this->handle); @fclose($this->handle);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
@@ -84,10 +92,4 @@ class FileStream implements Stream {
return feof($this->handle); return feof($this->handle);
} }
// -----------------------------------------------------------------------------------------------------------------
public function __clone() {
return new FileStream($this->file);
}
} }

View File

@@ -69,6 +69,17 @@ class BinaryStreamParser {
return $this->stream->readBytes($size); return $this->stream->readBytes($size);
} }
public function readCString($debug=false) {
$str = '';
while(true) {
$c = $this->stream->readBytes(1);
if($c == "\0") {
return $str;
}
$str .= (string) $c;
}
}
public function eof() { public function eof() {
return $this->stream->eof(); return $this->stream->eof();
} }