Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Jan 10, 2006, 21:08
Имам проблеми със следния скрипт на Perl със CGI интерфейс: Примерен код | #!/usr/bin/perl #************************************************************************* # # Програма за конвертиране на шльокавица към кирилица # Copyleft (C) 2005 Валентин Стойков <http://vstoykov.hit.bg/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #*************************************************************************
#*************************************************************************
use locale; use encoding 'utf8'; use utf8;
#require("/home/valentin/62c/modulelat2cyr.pm"); require("/home/vslivecd/62c/modulelat2cyr.pm"); #require("/usr/share/62c/modulelat2cyr.pm");
#*************************************************************************
my $in; if ($ENV{'REQUEST_METHOD'} eq "GET") { $in = $ENV{'QUERY_STRING'}; } else { $in = <STDIN>; }
sub strToHTML { my $text = shift; $text =~ s|\&|\&\;|g; $text =~ s|\"|\"\;|g; $text =~ s|<|\<\;|g; $text =~ s|>|\>\;|g; return $text; }
print <<EOT; Content-type: text/html
<html> <head> <title> Превод на шльокавица </title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style> </style> </head> <body>
<table align="center" BORDER=0 CELLSPACING=0 CELLPADDING=0 height="100%" width="100%"> <tr align="center"><td align="center">
EOT
if ($in ne "") {
print <<EOT;
<textarea cols=80 rows=15 style="font-size: 14pt; background: #98add5"> EOT
$in =~ tr/+=/ &/d; chomp($in); my %input = split(/&/,$in); $input_data=$input{"latinica"}; # Un-Webify plus signs and %-encoding $input_data =~ tr/+/ /; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $line=convert_line_lat2cyr($input_data); print strToHTML($line);
print <<EOT; </textarea>
EOT
}
else { print <<EOT;
<form action="form.pl" method="post">
<textarea name=latinica cols=80 rows=15 style="font-size: 14pt; background: #98add5"> </textarea> <br> <INPUT type=submit value=" Изпрати "> <INPUT type=reset value=" Изчисти "> </form>
EOT
}
print <<EOT;
</td></tr> </table>
</body> </html>
EOT
|
Проблемът се наблюдава, когато в бланката (формата) се попълни текст на кирилица. След конвертирането текстът, който е бил на кирилица се вижда на маймуни, а текстът на латиница се вижда на кирилица (каква ирония... шльокавицата да се чете нормално, а кирилицата - не).
Струва ми се, че проблемът е в този ред:
Примерен код | $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
Пробвай най-различни варианти, но не се получава:
Примерен код | $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%(([a-fA-F0-9][a-fA-F0-9]))/pack("U", hex($1.$2))/eg; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%(([a-fA-F0-9][a-fA-F0-9]))/chr(hex($1.$2))/eg;
$input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/pack("U", hex($1."00"), hex($2))/eg; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/pack("U", hex($1.$2))/eg; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/$1.$2." "/eg; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/"1=".$1." 2=".$2." "/eg; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/$1.$2." "/eg; $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("a", hex($1))/eg; $input_data =~ s/%([a-fA-F\d]+)/chr(hex($1))/ge;
|
Търсенето с Google не доведе до резултати.
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: в Jan 11, 2006, 00:55
Честно казано набързо прегелдах поста и не съм се задълбочовал много, но ти пращам изпозваното при мене решение: Примерен код | sub URL_decode { my $url = $_[0]; $url =~ tr/+/ /; $url =~ s/%([a-fA-F0-9]{2,2})/chr(hex($1))/eg; $url =~ s/<!--(.|\n)*-->//; return $url; }
$url_param =~ s/([;<>\*\|`&\$!?#\(\)\[\]\{\}:'"\\])/\\$1/g;
|
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Jan 11, 2006, 18:20
Твоето решение предполагам, че работи идеално на cp1251, но при мен не става. Ползвам UTF-8. Например "абв" при мен излглежда така "%D0%B0%D0%B1%D0%B2". За всяка буква има по два байта.
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Jan 11, 2006, 18:28
При опит с това: Примерен код | $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/pack("U", hex($1.$2))/eg; |
след конвертиране връща три квадрата с числа в тях: http://d.interbild.net/vstoykov/tmp/bugs/62c/abv_code.png Обърнете внимание на това, че числата съответстват на кодовете на буквите. Не виждам причина да се появяват квадрати вместо букви... Същото се получава и в този случай:
Примерен код | $input_data =~ s/%([a-fA-F0-9][a-fA-F0-9])%([a-fA-F0-9][a-fA-F0-9])/chr(hex($1.$2))/eg;
|
Не ми се иска интерфейсът да е на cp1251 и вътрешно да се прави конвертиране на UTF-8 (грозно е и няма да работи с букви различни от кирилицата и латиницата - не че на някой ще му трябва, но не е хубаво да се пише калпав софтуер - то и през миналия век не им е трябвало повече от 7 бита/символ за кодиране на текст...).
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: в Jan 11, 2006, 19:35
не съм в час с perl, но Примерен код | use locale; use encoding 'utf8'; use utf8;.... |
Не видях да се задава local и си мисля си дали той не е "C" ("POSIX"), когато се изпълнява скрипта ? Пробвал ли си да зададеш изрично en_US.UTF-8 ?
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Jan 11, 2006, 20:33
Махнах този ред: Примерен код | use encoding 'utf8';
|
от файловете form.pl и modulelat2cyr.pm и проблемът се реши. Все още не съм много наясно какво точно се получава, но щом работи - добре е.
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Jan 11, 2006, 21:04
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: CaBA в Jan 12, 2006, 14:09
Примерен код | #!/usr/bin/perl -C |
Цитат | -C [number/list] The "-C" flag controls some Unicode of the Perl Unicode features.
As of 5.8.1, the "-C" can be followed either by a number or a list of option letters. The letters, their numeric values, and effects are as follows; listing the letters is equal to summing the numbers.
I 1 STDIN is assumed to be in UTF-8 O 2 STDOUT will be in UTF-8 E 4 STDERR will be in UTF-8 S 7 I + O + E i 8 UTF-8 is the default PerlIO layer for input streams o 16 UTF-8 is the default PerlIO layer for output streams D 24 i + o A 32 the @ARGV elements are expected to be strings encoded in UTF-8 L 64 normally the "IOEioA" are unconditional, the L makes them conditional on the locale environment variables (the LC_ALL, LC_TYPE, and LANG, in the order of decreasing precedence) -- if the variables indicate UTF-8, then the selected "IOEioA" are in effect
For example, "-COE" and "-C6" will both turn on UTF-8-ness on both STDOUT and STDERR. Repeating letters is just redundant, not cumulative nor toggling.
The "io" options mean that any subsequent open() (or similar I/O operations) will have the ":utf8" PerlIO layer implicitly applied to them, in other words, UTF-8 is expected from any input stream, and UTF-8 is produced to any output stream. This is just the default, with explicit layers in open() and with binmode() one can manipu‐ late streams as usual.
"-C" on its own (not followed by any number or option list), or the empty string "" for the "PERL_UNICODE" environment variable, has the same effect as "-CSDL". In other words, the standard I/O handles and the default "open()" layer are UTF-8-fied but only if the locale environment variables indicate a UTF-8 locale. This behaviour follows the implicit (and problematic) UTF-8 behaviour of Perl 5.8.0.
You can use "-C0" (or "0" for "PERL_UNICODE") to explicitly disable all the above Unicode features.
The read-only magic variable "${^UNICODE}" reflects the numeric value of this setting. This is variable is set during Perl startup and is thereafter read-only. If you want runtime effects, use the three-arg open() (see "open" in perlfunc), the two-arg binmode() (see "binmode" in perlfunc), and the "open" pragma (see open).
(In Perls earlier than 5.8.1 the "-C" switch was a Win32-only switch that enabled the use of Unicode-aware "wide system call" Win32 APIs. This feature was practically unused, however, and the command line switch was therefore "recycled".)
|
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: в Jan 12, 2006, 18:33
Нещо се съмнявам че идеята ще стработи. tr функцията, ако следва поведението на командата, засега няма да стане: Примерен код | $ echo АБВАБВ | sed -e 's|А|x|g' -e 's|Б|y|g' xyВxyВ $ echo АБВАБВ | tr АБВ xyz zyzzzzzyzzzz $ locale charmap UTF-8 |
Бел.: в примера по-горе символите с главни букви са на кирилица ! А sed създава измамно впечатление, че работи ! Сигурно ли е, че tr и s в perl разбират от UTF-8 ?
"use locale;" не ми изглежда подходящо за web. Кой ще подаде на скрипта променливите като LANG LC_CTYPE LC_ALL : - първо трябва да са установени в обкръжението на процеса, които стартира web сървера; - после май трябва изрично да се укаже, кои променливи, да се предават на CGI; - а ако скрипта се стартира през mod_perl - да се види как се предават
Администрирането на такава система става много сложно!
Затова, в web приложение, моето предложение е да се ползва setlocale(..., "xx_YY.UTF_8") и да не се разчита на настройките на сървера и неговото обкръжение. Моето мнение е, че демоните и root трябва да работят без езикови настройки или в "C" ("POSIX").
Не трябва да се забравя, че символите в UTF-8 са с променлива дължина - от един до шест байта. Функциите tr и s, май, просто заменят поредици от байтове и оттук е моя скептицизим, че с тях може да се реши задачата. В решението трябва да се използва алгоритъм за обработка на символи. Бел.: символ != байт Поредица от байтове като "0xD0 0xD0 0xB0" не е валидна UTF-8 последователност от символи.
Може би трябва да се помисли за решение с iconv. Нещо такова: - конвертира се с iconv входния поток от UTF-8 в KOI-8 - някакви специфични пудри с латинските символи: например sh да стане ш на кирилица - вдига се 8-мия бит на останалите латинските символи - превръщане с iconv от KOI8-R в UTF-8 Незнам да ли ще удачно, понеже имам спомени от предишни дискусии, че имаше варианти, например от 'sh' в 'ш' или 'сх'.
Би трябвало да може и без iconv, но входния поток трябва да се обработва utf8-символ по utf8-символ.
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Jan 12, 2006, 23:09
Струва ми се, че успях да подкарам програмата на cp1251: http://vslivecd.openfmi.net/perl/form1251.plВ началото на form.pl и modu..1251.pl сложих: Примерен код | use encoding 'cp1251';
|
Тук са скриптовете: http://vslivecd.openfmi.net/62c/
Кеша на браузъра ми ли прави проблеми... един път програмата работи - следващия не... Или може би причината е другаде - когато съм се логнал през ssh към машината, където е сървъра - работи, когато изляза - спира да работи..
Титла: UTF-8 и URL encoding (x-www-form-urlencoded)
Публикувано от: vstoykov в Apr 10, 2006, 21:23
|