gzcompress + UTF-8 + Кириллица (или кракозябры в последних байтах вывода)

scam87

Новичок
gzcompress + UTF-8 + Кириллица (или кракозябры в последних байтах вывода)

Уважаемые участники форума, помогите, пожалуста, разрешить проблему!

Использую сжатие вывода gzip и кодировку UTF-8.
В конце выводимого содержимого вижу кракозыбры! :(
Пример html-разметки:
</body></i3&#65533;&#65533;d cl="r
в конце кракозябрики вместо закрывающего </html>

Вот заголовки, которые я получаю от своего скрипта:
PHP:
Date: Thu, 04 Jun 2009 11:26:37 GMT
Server: Apache/2.2.4 (Win32) mod_ssl/2.2.4 OpenSSL/0.9.8d PHP/5.2.4
X-Powered-By: PHP/5.2.4
Content-Encoding: gzip
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Pragma: no-cache
Last-Modified: Thu, 04 Jun 2009 11:26:37 GMT
Content-Length: 994
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Алгоритм работы скрипта:
- буферизация вывода
- захват буфера
- сжатие буфера
- отправка заголовков
- отправка сжатого буфера

Проблема наблюдается, только когда в html присутствуют русские символы!
Думаю, что проблема с вычислением длины отдаваемого содержимого:
с резирвирования 2 байтов вместо 1 под символы русского алфавита и вследствие этого, кракозябры в конце,
т.к. длина не соотвествует отдаваемому количеству информации.

Вроде везде использую безопасные multi byte (mb_*) функции,
в регулярках везде использую ключ "u" (работаем с utf).

Проблемный участок, где происходит сжатие.
При отключённом сжатии, всё ОК.

PHP:
header_set('Content-Encoding', $encoding); // $encoding = 'UTF-8'
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";

$page_size = mb_strlen($page_buffer); // $page_buffer - захваченный буфер
$crc32 = crc32($page_buffer);
        
$page_buffer = gzcompress($page_buffer, $compress_level);
        
$page_buffer = mb_substr($page_buffer, 0, mb_strlen($page_buffer)-4);

return ($page_buffer.pack('V', $crc32).pack('V', $page_size));
Где бага, не могу понять!

Что нужно исправить?
 

SiMM

Новичок
> проблема с вычислением длины отдаваемого содержимого
А зачем Вы используете mb_strlen? Вам же не количество символов нужно, а число байт - используйте strlen.
 

scam87

Новичок
Автор оригинала: SiMM
> проблема с вычислением длины отдаваемого содержимого
А зачем Вы используете mb_strlen? Вам же не количество символов нужно, а число байт - используйте strlen.
Полагаю, что да.
Что делать тогда? :)
Честно говоря, не понимаю, что делает строчка:
PHP:
$page_buffer = mb_substr($page_buffer, 0, mb_strlen($page_buffer)-4);
-~{}~ 04.06.09 16:23:

Исправил везде mb_ функции на обычные.
Вроде помогло.
Первоначально и были обычные, но, при постоянных обновлениях страниц, проявлялась такая бага. Не сразу, а как-то рандомно.
При использовании mb_ стала вылезать всегда :)
Сейчас всё ОК.
Если эта гадость опять вылезет - отпишу.
Спасибо.
 

dimagolov

Новичок
scam87
почитайте про ob_gzhandler. С его использованием весь этот код выкидывается и перед началом вывода вставляется
ob_start("ob_gzhandler", -1);
И ВСЕ!
 

scam87

Новичок
dimagolov,
я немного дизинформировал участников форума :)
проблема осталась, когда я вернул функции обратно (просто я отключал сжатие вовсе и забыл про это).
по поводу ob_gzhandler я прочёл.
Как в вашем случае управлять коэффициентом сжатия?

-~{}~ 04.06.09 23:54:

Проблему решил.

Стёр к чертям:
PHP:
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; 

$page_size = mb_strlen($page_buffer); // $page_buffer - захваченный буфер 
$crc32 = crc32($page_buffer); 
         
$page_buffer = gzcompress($page_buffer, $compress_level); 
         
$page_buffer = mb_substr($page_buffer, 0, mb_strlen($page_buffer)-4); 

return ($page_buffer.pack('V', $crc32).pack('V', $page_size));
Заменил на:
PHP:
return gzencode($page_buffer, $compress_level)
:)
 

dimagolov

Новичок
Как в вашем случае управлять коэффициентом сжатия?
scam87, а зачем им управлять? как показали эксперементы с gzcompress, уровень сжатия практически ни на что не влияет.

но если ты китайский комсомолец, то продолжай свои упражнения в ластах стоя в гамаке :)
 

scam87

Новичок
dimagolov,
я нормальный китаец :)
решение в предыдущем посте, ИМХО, более гибко (контроль над уровнем сжатия)
Если писать свою функцию "ob_gzhandler", то одеваем ласты и прыгаем на гамаке :)
Всем спасибо.
И всё таки будет интересно, если кто-то укажет на багу :)
 

cDLEON

Онанист РНРСlub
Тебе уже указали
ты знаешь в чём разница между
[m]strlen[/m]
[m]mb_strlen[/m] ?
 

scam87

Новичок
cDLEON, естественно :)
strlen - вернёт число байт.
mb_strlen - число символов, учитывая то, что некоторые символы могут быть > 1байт.
кстати, в этом участке кода эти 2 функции возвращают одно и то же значение :)
 
Сверху