Статья размещена автором Бетке Сергей Сергеевич

WordPress 3.2.1 и проблема с кодировкой в админке, AJAX, XMLRPC

Честно говоря, проблему с юникодом в WordPress (в консоли) наблюдаю давно, просто особо не мешала. Однако, проблема проявилась и при попытке чтения статей в Live Writer, а с этим смириться уже не мог. Найдём проблему и исправим её.

Корень проблемы удалось обнаружить с помощью Network Monitor.  В ответах, как и ожидал, увидел следующее:

Content-Type: text/xml;
charset=windows-1251
...

...

Вопрос – откуда кодировка, если у меня в настройках блога – UTF-8, в настройках базы – аналогично? Всё просто – смотрим php.ini:

; As of 4.0b4, PHP always outputs a character encoding by default in
; the Content-type: header. To disable sending of the charset, simply
; set it to be empty.
;
; PHP's built-in default is text/html
default_mimetype = "text/html"
default_charset = "windows-1251"

Итого, два решения. Первое – халявное: правим php.ini. Решение вполне рабочее. Но есть и второе решение, правильное – исправим баги WordPress.

Сразу приведу решение. Версия WordPress – 3.2.1, файл wp-includes/class-IXR.php, было:

function output($xml)
{
    $xml = ''."\n".$xml;
    $length = strlen($xml);
    header('Connection: close');
    header('Content-Type: text/xml;', true);
    header('Content-Length: '.$length);
    header('Date: '.date('r'));
    echo $xml;
    exit;
}

должно быть:

function output($xml)
{
    $xml = ''."\n".$xml;
    $length = strlen($xml);
    header('Connection: close');
    header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true);
    header('Content-Length: '.$length);
    header('Date: '.date(DATE_RFC1123));
    echo $xml;
    exit;
}

Файл wp-includes/class-wp-admin-ajax-response.php, было:

function send() {
    header('Content-Type: text/xml');
    echo "";
    foreach ( (array) $this->responses as $response )
    echo $response;
    echo '';
    die();
}

должно быть:

function send() {
    $xml = "";
    foreach ( (array) $this->responses as $response )
    $xml .= $response;
    $xml .= '';
    $length = strlen($xml);
    header('Content-Type: text/xml; charset=' . get_option('blog_charset'));
    header('Content-Length: '.$length);
    header('Date: '.date(DATE_RFC1123));
    echo $xml;
    die();
}

И добавка от 02.12.2011: нашёл ещё один “глюк” при обновлении плагинов. Исправлять будем wp-admin/includes/template.php. Было:

function iframe_header( $title = '', $limit_styles = false ) {
    show_admin_bar( false );
    global $hook_suffix, $current_screen, $current_user, $admin_body_class, $wp_locale;
    $admin_body_class = preg_replace('/[^a-z0-9_-]+/i', '-', $hook_suffix);
    $admin_body_class .= ' iframe';

?>
 >

; charset=" />

А должно быть:

function iframe_header( $title = '', $limit_styles = false ) {
    show_admin_bar( false );
    global $hook_suffix, $current_screen, $current_user, $admin_body_class, $wp_locale;
    $admin_body_class = preg_replace('/[^a-z0-9_-]+/i', '-', $hook_suffix);
    $admin_body_class .= ' iframe';

    header('Connection: close');
    header('Content-Type: text/html; charset=' . get_option('blog_charset'), true);
    header('Expires: '.date(DATE_RFC1123));
    header('Date: '.date(DATE_RFC1123));
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Cache-Control: post-check=0, pre-check=0', FALSE);
    header('Pragma: no-cache');

?>
 >

; charset=" />

И всё, всё работает успешно!

Отзывы » (8)

  1. Опубликовал соответствующее замечание в форуме WordPress, будем ждать реакции разработчиков.

    • Судя по всему, зря я жду реакции, потому как bug reports следует подавать иначе. Нашёл целую статью на тему, как правильно подавать bug reports по ядру wordpress: http://codex.wordpress.org/Reporting_Bugs.
      Открытых билетов с проблемами с кодировкой в заголовках нашёл много:
      - при формировании robots.txt: 14069.
      - при AJAX ответах 11034. Но указанный баг — это ещё один баг, а не описанный в моей статье. Поэтому добавляю свой билет для этого бага. Открыл билет по всем правилам: 19448. Буду благодарен Вам, если Вы поддержите этот ticket своими комментариями.
      - на эту же тему, общий вопрос 10817
      - о проблемах с национальными символами в ЧПУ 10249
      - о проблемах с кодировкой в XMLRPC 4794, выше проблема с решением описана, но и в указанном багрепорте решение уже так же приведено, ему уже 10 месяцев. Проблема, видимо, в том, что создавался patch аж для версии 2.2.2. Вернул статус «бага» данному билету (почему изменили его до этого на «усовершенствование», хотя он не позволял использовать Live Writer, по сути). Так же выложил свой патч, надеюсь на реакцию команды разработчиков.

      P.S. Рецепт для создания патчей к ядру WordPress нашёл здесь: http://asymptomatic.net/2005/12/03/586/how-to-patch-wordpress.

  2. Сегодня при обновлении плагинов нашёл ещё одну ошибку — в wp-admin/includes/template.php. В статье уже привёл рецепт и для этого файла.
    P.S. Да, разработчики позаботились о meta тегах в генерируемом контенте, но заголовки http протокола никто ещё не отменял…

  3. Дмитрий:

    Спасибо, помогло. Не совсем понял по багу от 02.12 — не нашел файл template в директории. Версия WP 3.3

    • Честно говоря, больше похоже на какой-то «глюк». В 3.2 точно этот файл был, в бетах 3.3 и в rc так же был. Теперь смотрю в 3.3 файл admin.php, и в 43 строке вижу подключение файла template.php. Да и в svn хранилище он есть — скачал ночную сборку версии 3.3 — есть он там. Только номер строки, в которой начинается определение функции iframe_header теперь иной — 1371. А в остальном изменения прежние. Рекомендую лучше сделать следующие поправки в том же файле (для версии WP 3.3):

      function _wp_admin_html_begin() {
      	status_header( 200 );
      	nocache_headers();
      	header('Content-Type: text/html; charset=' . get_option('blog_charset'));
      ?>
      <!DOCTYPE html>
      

      Проверено, работает. Так всё-таки более универсально, о кроссбраузерности и корректности заголовков во многом позаботятся разработчики WordPress в этом случае.

  4. Итого, коллеги, похоже в версии 3.5 нас ждёт исправление объявленных выше багов. Как минимум, три из перечисленных мною билетов планируется закрыть в версии 3.5. Ждёмс…

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка