Ошибки конвертера для IPB3

Ошибка

mySQL query error: INSERT INTO ipb3groups (g_title,g_hide_from_list,g_use_pm,g_max_messages,g_max_mass_pm,prefix,suffix,g_perm_id) VALUES('Русские буквы в названии группы{тут знак вопроса или символ не читаемый в UTF-8}',1,0,0,0,'','',7)<br /> <br /> <br /> >SQL error: Incorrect string value: '\xD0' for column 'g_title' at row 1<br /> <br /> SQL error code: 1366<br /> <br /> Date: Thursday 17th o September 2009 11:48:44 AM<br />

Условия возникновения:

Мигрировал с phpBB3 на IPB 3 (ver 3.0.3)
Использовалась последняя версия конвертера с сайта производителя (на 17.09.2009)
При конвертации Member Groups

В моём случае ошибка вызвана в файле:
admin/applications_addon/ips/convert/sources/lib_master.php
/**
* IPS Converters
* Application Files
* Library functions
* Last Update: $Date: 2009-09-01 10:53:43 +0100 (Tue, 01 Sep 2009) $
* Last Updated By: $Author: mark $
*
* @package IPS Converters
* @author Mark Wade
* @copyright © 2009 Invision Power Services, Inc.
* @link http://external.ipsl.../?p=converthelp
* @version $Revision: 357 $
*/
<br /><br />..<br />
// Line: 1656
$info['g_title'] = substr($info['g_title'], 0, 32);

Виной всему встроенная php функция substr(): http://ru2.php.net/manual/en/function.substr.php
Использовать её на мультибайт строках не безопасно. Например utf8 который используеться по умолчанию в ipb3 и в phpBB версии 3.
Поэтому скорее всего попытка переахть с других форумах где используеться Юникод тоже вызовет ошибку.

К сведенью: я быстренько пробежался по коду IPB 3 и обноружил множество мест, где использовался substr(), очень возможно возникновение похожих ошибок и в других местах и при других обстоятелствах.

Как лечить:

Способа есть по крайней мереnhb. Два из них связанны с использованием стандартного php модуля PHP_MBSTRING.

  1. Пожалуй самый правильным в данном случае, при использовании PHP 5-ой будет включение опции mbstring.func_overload (http://ru2.php.net/manual/en/mbstring.overload.php). Модуль mbstring нужно предварительно активировать. Напрмер так:
    php.ini
    mbstring.func_overload = 7
    Можно и с использование функции ini_set(), но придется модифицировать файлы IPB. А этот способ тем и хорош, что не меняються оригинальные файлы форума. Но может привести к ошибкам, там где текстовые функции используються для бинарных операций. А потому после конвертации mbstring.func_overload настоятельно рекомендую отключить.
  2. Отредактировать файл lib_master.php заменив substr() на mb_substr(). Модуль mbstring нужно предварительно активировать.
  3. Использховать встроенную в IPB функцию IPSText::mbsubstr().
    Этим способом и должны были воспользоваться разработчики IPB. Но почему то этого не сделали.. )

Также замечу, что использование последних двух вариантов не спасёт вас от подобной ошибки в других местах.

Немного философии

Включением опции mbstring.func_overload способно вылечить множество проблем и спользованием Юникода, в качестве кодировки в движке, слабо приспособленного для его использование. Фактически строковые функции PHP Это единственное узкое место с точки зрения Юникода.
Пример: phpbb2 не поддерживает Юникод. Но чтобы заставить его корректно работать достаточно включить опцию mbstring.func_overload (не забыв предварительно перекодировать базу, lang файлы, изменить кодировку в настройках, стилях и параметрах подключения к базе).

Почему так получаться? Потому что php на уровне ядра не подозревает о существовании Юникода. В отличии скажем от Perl (который давно перешёл на Юникод) или Java (в котором юникод был с самого начала), в php поддержку Юникода нам обещают только в шестой версии. Решит ли это проблему с использованием строковых функций ядра на Строках с юникодом. Как например в случае с substr() ? Незнаю. Покажет время. Хотя RC версии php6 уже доступны. Кому не ленива - могут проверить.

Что же остаться программисту? Всегда (если не требеутся обработка именно бинарных данных) использовать функции с префиксом mb_ из модуля PHP_MBSTRING. Напомню, что использование строковых функций вроде substr() на бинарных данных в свою очередь тоже не являться безопасным. Во-первых потому, что эти функции могут быть перезагруженны в модуле PHP_MBSTRING. Во-вторых реализация этих функций действительно может измениться в последующих версиях PHP. А всё потому, что эти функции по хорошему не предназначенны для обработки бинарных данных.

Возможно самым самым универсальным вариантом будет использование дополнительного пользовательского класса. Вроде класса IPSText из IPB3, в котором переопределены все строковые функции. Это безусловно усложнит программу и увеличит время выполнение. Но сделает код менезависимым от переменного окружения.

И на последок: скорее всего рассматриваемая проблема решена на уровне фреймфорков или есть интересные варианты в PEAR. Поэтому если вы используете такие инструменты программирования - лучше для начала поискать там.

Ссылки по теме

Подробнее о том, как конфигурить php можно почитать сдесь: http://ru2.php.net/manual/en/ini.php

ie8 bug in css: @charset

И снова здравствуйте.
Начинаю публиковать свою выкладку свеженадоенных неприятностей в «самом лучшем» браузере.

Есть такая штука в css — @charset. Позволяет в явном виде указывать кодировку документа со стилями.
Оператор указываться в самом начале CSS файла:
@charset "utf-8";
Рекомендовано к использованию W3C: Tutorial: Character sets & encodings in XHTML, HTML and CSS

А теперь внимание! в IE8 CSS фай с такой диклорацией перестаёт читаться полностью. Я не проверял все документотипы, у меня в рамках XHTML 1.0 Strict ситуация однозначная.

Кодировку можно указать и непосредственно в <link>, только вот при изменении кодировки css файла придётся править все линки. а для вшених css файлов ситуация в двойне неприятная.
Разуметься глюк незначительный. но всё равно досадно.

  • Опубликовано: 30.06.2009
  • Метки: , ,