Двоичная совместимость между gzdecode () и inflate_add ()

Некоторое время назад я написал небольшую библиотеку WebSocket и обнаружил, что добавить поддержку gzip на удивление легко. Я не до конца осознавал, что deflate_init() / deflate_add() / inflate_init() / inflate_add() функции были на самом деле только для PHP 7, и теперь я хотел бы иметь возможность запускать мой сервер WebSocket в среде PHP 5.

Моя проблема в том, deflate_add() производит вывод, который немного отличается от gzdeflate() — на один символ в тестовом примере ниже.

deflate_add()/inflate_add()Подход работает отлично в браузере, поэтому вывод gzdeflate() неправильный. я догадываюсь gzdeflate()/gzinflate() используете zlib с различными опциями — что-то, связанное с состоянием потока, может быть? — и это заставляет все рушиться.

В конечном итоге я хочу знать, смогу ли я убедить PHP-функции zlib 5-й эпохи выводить «правильные» дефлированные данные.


Прежде всего, deflate_init()/deflate_add()подход, который я использовал на PHP 7:

$data = "ABC";

$ctx = deflate_init(ZLIB_ENCODING_RAW);

// unfortunately I can't find the gigantic blog post with example code
// that I learned from :(, but it contained the Ruby equivalent of the
// the substr() below. I blinked at it a bit but apparently this is how
// it's done.
$deflated = substr(deflate_add($ctx, $data, ZLIB_SYNC_FLUSH), 0, -4);

// $deflated is now "rtr\6\0"
$ictx = inflate_init(ZLIB_ENCODING_RAW);

$data2 = inflate_add($ictx, $deflated, ZLIB_NO_FLUSH);

// $data2 is now "ABC"

Вот что произойдет, если я использую gzdeflate()/gzinflate():

$data = "ABC";

$deflated = gzdeflate($data, 9, ZLIB_ENCODING_RAW);

// $deflated is now "str\6\0"
$output = gzinflate($deflated);

// $output is now "ABC"

Пытаясь gzinflate() выход inflate_add() производит data error. Как TL; DR:

print gzinflate("rtr\6\0")."\n"; // will bomb out

print gzinflate("str\6\0")."\n"; // prints "ABC"

1

Решение

То, что вы называете правильно, неверно, а то, что вы называете неправильно, правильно.

С deflate_add вы намеренно создаете неопределенный, то есть недопустимый, дефляционный поток. Я понятия не имею. (По-видимому, и вы, поскольку это произошло из «гигантского поста в блоге», который вы не можете найти.) Это делается с помощью ZLIB_SYNC_FLUSH который завершает текущий блок deflate и добавляет пустой сохраненный блок. substr(,,-4) удаляет большую часть этого пустого сохраненного блока в конце, оставляя вас с неполным, недопустимым потоком инфляции, преждевременно заканчивающимся в середине сохраненного блока.

gzdeflate с другой стороны, создается правильно завершенный поток дефлятирования, причем один блок дефляции помечается как последний блок. Единственная разница между двумя потоками — это первый (наименее значимый) бит, который равен 1, чтобы обозначить последний блок.

Вы не говорите, как правильно завершенный поток дефлята «заставляет все рушиться». В любом случае вы можете создать правильно завершенный поток deflate_add используя ZLIB_FINISH вместо ZLIB_SYNC_FLUSHи отказываясь от substr,

Нет способа создать неверный поток с дефляцией gzdeflate, если ты об этом. Вы не можете просто изменить первый бит, так как для большей строки последний блок может не быть первым блоком.

-1

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

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

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