谈论这个:http://www.win-rar.com/index.php?id=24&kb_article_id=162
我可以通过执行以下操作来计算归档标头(MAIN_HEAD)的正确CRC:
$crc = crc32(mb_substr($data, $blockOffset + 2, 11, '8bit'));
$crc = dechex($crc);
$crc = substr($crc, -4, 2) . substr($crc, -2, 2);
$crc = hexdec($crc);
第一行将“字段的CRC HEAD_TYPE设置为RESERVED2 ”作为文档中的状态。正如我所指出的,它适用于归档头。
当我尝试计算文件头的CRC时,它总是会因为未知原因而吐出错误的CRC。我做的文档说 - “字段从HEAD_TYPE到FILEATTR ”,但它根本不起作用。我还尝试了不同的读取长度变化,以防文档错误,实际上可能是从HEAD_TYPE到FILE_NAME 。一切都没有成功。
任何人都可以给我一个暗示吗?我还检查了unrar源代码,但它并没有让我更聪明,可能是因为我根本不懂C语言......
答案 0 :(得分:1)
我写了一些做同样事情的代码。这是一些额外的片段,以便更好地理解:
$this->fh = $fileHandle;
$this->startOffset = ftell($fileHandle); // current location in the file
// reading basic 7 byte header block
$array = unpack('vheaderCrc/CblockType/vflags/vheaderSize', fread($this->fh, 7));
$this->headerCrc = $array['headerCrc'];
$this->blockType = $array['blockType'];
$this->flags = $array['flags'];
$this->hsize = $array['headerSize'];
$this->addSize = 0; // size of data after the header
// -- check CRC of block header --
$offset = ftell($this->fh);
fseek($this->fh, $this->startOffset + 2, SEEK_SET);
$crcData = fread($this->fh, $this->hsize - 2);
// only the 4 lower order bytes are used
$crc = crc32($crcData) & 0xffff;
// igonore blocks with no CRC set (same as twice the blockType)
if ($crc !== $this->headerCrc && $this->headerCrc !== 0x6969 // SRR Header
&& $this->headerCrc !== 0x6a6a // SRR Stored File
&& $this->headerCrc !== 0x7171 // SRR RAR block
&& $this->blockType !== 0x72 // RAR marker block (fixed: magic number)
) {
array_push($warnings, 'Invalid block header CRC found: header is corrupt.');
}
// set offset back to where we started from
fseek($this->fh, $offset, SEEK_SET);
我在几个SRR文件上测试了它,它按预期工作。我开始阅读基本的7字节标题。标题的大小可以在那里找到。我用它来获取crc32函数的正确数据量。我注意到当你将它转换为十六进制时,你可以在比较时得到误报:'0f00'!='f00'。你需要用零填充它。这就是为什么我保留crc32()和unpack()的十进制表示来进行比较。此外,如果设置了一些标题标志,则文件块的字段数可能会有所不同:您可能采用了错误的大小。