Как получить Perl для чтения значений из моей HTML-формы как Unicode? - PullRequest
2 голосов
/ 01 апреля 2011

У меня есть HTML-форма, которая отправляет данные на страницу .cgi. Вот HTML:

<HTML>

<BODY BGCOLOR="#FFFFFF">

    <FORM METHOD="post" ACTION="test.cgi">


        <B>Write to me below:</B><P>
        <TEXTAREA NAME="feedback" ROWS=10 COLS=50></TEXTAREA><P>

        <CENTER>
            <INPUT TYPE=submit VALUE="SEND">
            <INPUT TYPE=reset VALUE="CLEAR">
        </CENTER>

    </FORM>

</BODY>
</HTML> 

Вот скрипт perl для test.cgi:

#!/usr/bin/perl

use utf8;
use encoding('utf8');
require Encode;
require CGI;


# The following accepts the data from the form and puts it in %FORM

if ($ENV{'REQUEST_METHOD'} eq 'POST') {
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

    @pairs = split(/&/, $buffer);

    foreach $pair (@pairs) {
        ($name, $value) = split(/=/, $pair);
        $value =~ tr/+/ /;
        $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

    $FORM{$name} = $value;
    }

# The following generates the html for the page

    print "Content-type: text/html\n\n";
    print "<HTML>\n";
    print "<HEAD>\n";
    print "<TITLE>Thank You!</TITLE>\n";
    print "</HEAD>\n";
    print "<BODY BGCOLOR=#FFFFCC TEXT=#000000>\n";  
    print "<H1>Thank You!</H1>\n";
    print "<P>\n";
    print "<H3>Your feedback is greatly appreciated.</h3><BR>\n";
    print "<P>\n<P>\n";
    print "The user wrote:\n\n";
    print "<P>\n";

# This is print statement A
    print "$FORM{'feedback'}<br>\n";

    $FORM{'feedback'}=~s/(\w)/ $1/g;

# This is print statement B
    print "$FORM{'feedback'}\n";

    print "</BODY>\n";
    print "</HTML>\n";
    exit(0);
}

Это все работает так, как должно, если пользователь вводит текст на английском языке. Тем не менее, это в конечном итоге будет использоваться в продукте, где пользователь будет вводить текст на китайском языке. Итак, вот пример проблемы. Если пользователь вводит в форму «中文», то «Печать выписки А» печатает «中文». Однако оператор Print B (который печатает значение $ после выполнения регулярного выражения) печатает "& # 2 0 0 1 3; & # 2 5 9 9 1;". Однако я хочу, чтобы он напечатал «中 文». Если вы хотите это увидеть, перейдите на http://thedeandp.com/chinese/input.html и попробуйте сами.

Итак, в основном я понял, что когда perl читает в форме, он просто обрабатывает каждый байт как символ, поэтому регулярное выражение добавляет пробел между каждым байтом. Китайские иероглифы используют юникод, поэтому это несколько байтов на символ. Это означает, что регулярное выражение разбивает юникод с пробелом между байтами, и это то, что производит вывод, видимый в операторе Print B. Я пробовал такие методы, как $ value = Encode :: decode_utf8 ($ value), чтобы обработать perl это как Unicode, но пока ничего не работает.

Ответы [ 3 ]

4 голосов
/ 01 апреля 2011

Что стиль CGI может быть улучшен при исправлении проблемы с декодированием кодирования. Попробуйте это -

use strict;
use warnings;
use Encode;
use CGI ":standard";
use HTML::Entities;

print
    header("text/html; charset=utf-8"),
    start_html("Thank you!"),
    h1("Thank You!"),
    h3("Your feedback is greatly appreciated.");

if ( my $feedback = decode_utf8( param("feedback") ) )
{
    print
        p("The user wrote:"),
        blockquote( encode_utf8( encode_entities($feedback) ) );
}

print end_html();

Правильное кодирование и декодирование между октетами / байтами и utf-8 необходимо, чтобы избежать неожиданностей и позволить Perl вести себя так, как вы ожидаете.

Например, вы можете оставить это в -

    h4("Which capitalizes as:"),
    blockquote( encode_utf8( uc $feedback ) );

И посмотрите, как работает преобразование символов: å ™ ç∂®r £ ➟ Å ™ Ç∂®R £

Обновление: добавлено encode_entities. НИКОГДА не печатать пользовательский ввод обратно без выхода из HTML. Обновление до обновления: что в конечном итоге приведет к выходу из utf-8 в зависимости от настроек (например, вы можете использовать только экранирование ['"<>]) ...

0 голосов
/ 01 апреля 2011

Если вы посмотрите на источник для страницы благодарности, содержимое будет выглядеть так:

&#20013;&#25991;<br>
&# 2 0 0 1 3;&# 2 5 9 9 1;

Таким образом, похоже, что $FORM{'feedback'} приходит как сущность HTML, а не как UTF-8.Вам, вероятно, нужно преобразовать эти объекты в реальные символы UTF-8, прежде чем работать с данными, я не уверен, что лучший способ сделать это.

0 голосов
/ 01 апреля 2011

Какую версию Perl вы используете?Это работает для меня с v5.10.1 на i686-cygwin-thread-multi-64int:

perl -E 'use utf8; use encoding("utf8"); $_="中文"; say; s/(\w)/$1 /g; say'

Вывод:

中文
中 文

Я уверен, что вы прочитали perlunicode ?

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