Контрольный список для перехода на Unicode с Perl - PullRequest
19 голосов
/ 17 сентября 2010

Я помогаю клиенту преобразовать свой сайт объявлений Perl для плоских файлов из ISO-8859-1 в Unicode.

Поскольку это мой первый раз, я хотел бы знать, заполнен ли следующий «контрольный список». В тестировании все работает хорошо, но я могу упустить что-то, что может произойти только в редких случаях.

Это то, что я сделал до сих пор (простите, что я включил только "сводные" примеры кода):

  1. Убедитесь, что файлы всегда читаются и записываются в UTF-8:

    use open ':utf8';
    
  2. Убедитесь, что вход CGI получен как UTF-8 (сайт не использует CGI.pm):

    s{%([a-fA-F0-9]{2})}{ pack ("C", hex ($1)) }eg;    # Kept from existing code
    s{%u([0-9A-F]{4})}{ pack ('U*', hex ($1)) }eg;     # Added
    utf8::decode $_;
    
  3. Убедитесь, что текст напечатан в формате UTF-8:

    binmode STDOUT, ':utf8';
    
  4. Убедитесь, что браузеры интерпретируют мой контент как UTF-8:

    Content-Type: text/html; charset=UTF-8
    <meta http-equiv="content-type" content="text/html;charset=UTF-8">
    
  5. Убедитесь, что формы отправляют UTF-8 (вероятно, нет необходимости, если задана кодировка страницы):

    accept-charset="UTF-8"
    
  6. Не думайте, что мне нужно следующее, поскольку встроенный текст (меню, заголовки и т. Д.) Есть только в ASCII:

    use utf8;
    

Это выглядит разумно или я что-то упустил?

РЕДАКТИРОВАТЬ: Я должен также упомянуть, что мы будем запускать одноразовый пакет для чтения всех существующих файлов текстовых данных и сохранения их в кодировке UTF-8.

Ответы [ 2 ]

26 голосов
/ 17 сентября 2010
  • Слой :utf8 PerlIO является недостаточно строгим .Он разрешает ввод, который удовлетворяет структурным требованиям последовательностей байтов UTF-8, но для хорошей безопасности вы хотите отклонить материал, который на самом деле не является допустимым Unicode.Замените его везде слоем PerlIO::encoding, таким образом: :encoding(UTF-8).

  • По той же причине всегда Encode::decode('UTF-8', …), а не Encode::decode_utf8(…).

  • затруднить декодирование, исключение, сравните:

    perl -E'use Encode qw(decode); say decode(q(UTF-8), qq(\x{c0})); say q(survived)'
    perl -E'use Encode qw(decode); say decode(q(UTF-8), qq(\x{c0}), Encode::FB_CROAK); say q(survived)'
    
  • Вы не заботитесь о суррогатных парах в обозначении %u,Это единственная серьезная ошибка, которую я вижу в вашем списке.2. написано правильно как:

    use Encode qw(decode);
    use URI::Escape::XS qw(decodeURIComponent);
    $_ = decode('UTF-8', decodeURIComponent($_), Encode::FB_CROAK);
    
  • Не связывайтесь с функциями из модуля utf8.В его документации так сказано.Он предназначен для прагмы, чтобы сказать Perl, что исходный код находится в UTF-8.Если вы хотите выполнить кодирование / декодирование, используйте модуль Encode.

  • В любом случае добавьте прагму utf8 в каждый модуль.Это не повредит, но вы будете поддерживать код на будущее, если кто-то добавит эти строковые литералы.См. Также CodeLayout::RequireUseUTF8.

  • Employ encoding::warnings, чтобы выкурить оставшиеся неявные обновления.Проверьте для каждого случая, предназначено ли это / необходимо.Если да, преобразуйте его в явное обновление с Unicode::Semantics.Если нет, то это подсказка, что у вас должен был быть ранее этап декодирования.Документы от http://p3rl.org/UNI дают совет немедленно декодировать после получения данных из источника.Пройдите по местам, где код читает / записывает данные, и убедитесь, что у вас есть шаг декодирования / кодирования, либо явно (decode('UTF-8', …)), либо неявно через слой (use open pragma, binmode, 3 аргумента в форме * 1064).*).

  • Для отладки: если вы не уверены, какая строка находится в переменной и в каком представлении в определенное время, вы не можете просто print, использовать инструменты Devel::StringInfo и Devel::Peek вместо.

8 голосов
/ 17 сентября 2010

Ты всегда что-то упускаешь. Проблема обычно в неизвестных неизвестных. :)

Эффективное программирование на Perl содержит главу по Unicode, которая охватывает многие основы Perl. Тем не менее, один пункт, который мы не рассмотрели, это все, что вам нужно сделать, чтобы ваш сервер баз данных и веб-сервер делали все правильно.

Некоторые другие вещи, которые вам нужно сделать:

  • Обновите до последней версии Perl. Юникод стал намного проще в 5,8, а еще проще в 5,10.

  • Убедитесь, что содержимое сайта преобразовано в UTF-8. Вы могли бы написать сканер, чтобы поразить страницы и найти символ замены Unicode (тот, который выглядит как ромб с вопросительным знаком на нем). Давайте посмотрим, смогу ли я сделать это в StackOverflow: & # xfffd;

  • Убедитесь, что ваш сервер баз данных поддерживает UTF-8, что вы настроили таблицы со столбцами, поддерживающими UTF-8, и что вы указываете DBI использовать поддержку UTF-8 в своем драйвере (некоторые из этих в книге).

  • Убедитесь, что все, что смотрит на @ARGV, переводит элементы из локали командной строки в UTF-8 (это в книге).

Если вы найдете что-нибудь еще, пожалуйста, сообщите нам об этом, ответив на ваш вопрос с тем, что мы оставили. ;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...