Есть ли что-то особенное в формате windows MSZIP или CFDATA в файлах cab?

Я читаю CAB-файлы на PHP и столкнулся с проблемой при извлечении.
Вся структура кабины тщательно анализируется, но когда я сжимаюсь (методом deflate, rfc 1951), данные и gzinflate() на нем происходит нечто странное:
Первый блок каждой папки распаковывается без каких-либо проблем, но если я пытаюсь распаковать любой из блоков N + 1, gzinflate завершается с ошибкой.

Я проверил, что скрипт правильно выбирает данные (я ищу CK теги) и использует правильные смещения.

Чтобы понять проблему, позвольте мне описать формат cab и mszip. [увидеть больше на https://msdn.microsoft.com/en-us/library/bb417343.aspx]

CAB-файл содержит:

  1. HEADER состав
  2. N из FOLDER состав
  3. N из ФАЙЛ состав
  4. N из ДАННЫЕ состав

ФАЙЛ Структура имеет следующие поля:

  • folderId
  • inFolderOffset
  • uncompressedSize

ДАННЫЕ это сжатые данные порциями. Это также относится к конкретным папка и имеет следующие поля:

  • folderId
  • compressedSize
  • uncompressedSize
  • uncompressedOffset

Для извлечения любого содержимого файла необходимо:

  1. Читать и распаковывать блоки, в которых присутствует этот файл

    +----------+----------+             +----------+----------+----------+
    |  block 0 |  block 1 |             |  block 0 |  block 1 |  block 2 |
    +----------+----------+             +----------+----------+----------+
    ===========                     ================================
    |   file  |                     |       file 0       |  file 1 |
    ===========                     ================================
    
  2. Соединить распакованные блоки

  3. Вырезать из fileOffset в fileOffset + fileSize

Формат MSZIP

Это сжатые с помощью дефлята данные с 2-байтовым префиксом (CK). Подробно: http://interoperability.blob.core.windows.net/files/MS-MCI/[MS-MCI].pdf

Одна вещь, которая может иметь значение, это: расшифровка
деревья ДОЛЖНЫ отбрасываться после каждого блока RFC 1951, но буфер истории ДОЛЖЕН поддерживаться.
(7-я страница).

Я не знаю много о сжатии с дефляцией, но я использую для этого gzinflate. Это неправильно? Значит ли это, что я должен написать другую реализацию декомпрессора deflate?

https://github.com/wapmorgan/CabArchive/blob/master/src/CabArchive.php

Чтобы проверить распаковку любого блока, просто выполните:

<?php
$cab = new CabArchive('any-cab.cab');
// Next command decompress first MSZIP block - successfully
$cab->decompressBlocks(0, [0]);
// And this command failed with "data error"$cab->decompressBlocks(0, [1]);

0

Решение

Вам нужно передать последние 32 Кбайта несжатого (или все они, если меньше 32 Кбайт) на инфляцию следующей записи как предустановленный словарь. Функция PHP inflate_init поддерживает это. Однако смотрите комментарии — inflate_init может быть глючит

Также вам нужно предоставить все нули в качестве исходного словаря для первой инфляции.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]