PDA

Показать полную графическую версию : [решено] декодирование в php после javascript:encode


VeshchiyOleg
25-12-2006, 17:42
при передаче данных в XMLHTTPRequest из javascript русские символы из кодировки 1251 приходят в php в некоей кодировке, которую называют iso8859-1 (в доках по php), хотя на самом деле русские символы присутствуют только в iso8859-5. может это и одно и то же, однако обратно они приходят в ней же, а нифига не в 1251. iconv и прочие конверторы использовать не имею ни желания ни возможности - на локальной машине их нет, а я добавлять чего-либо не умею и не надо меня этому учить. а на сервере и играться как-то кощунственно и туда тоже надо доставлять дополнительные расширения. потом... возможно ведь и использование пользователями других символов, которые не будут входить уже в iso8859-5. следовательно перед отправкой я делаю строке encode в javascript`е. все символы (русские) приходят в виде %u0... для их переконвертации я написал свой обработчик:
function global_decode(
$str
) {
return strtr($str, array(
'%u0401' => 'Ё',

'%u0410' => 'А',
'%u0411' => 'Б',
'%u0412' => 'В',
'%u0413' => 'Г',
'%u0414' => 'Д',
'%u0415' => 'Е',
'%u0416' => 'Ж',
'%u0417' => 'З',
'%u0418' => 'И',
'%u0419' => 'Й',
'%u041A' => 'К',
'%u041B' => 'Л',
'%u041C' => 'М',
'%u041D' => 'Н',
'%u041E' => 'О',
'%u041F' => 'П',
'%u0420' => 'Р',
'%u0421' => 'С',
'%u0422' => 'Т',
'%u0423' => 'У',
'%u0424' => 'Ф',
'%u0425' => 'Х',
'%u0426' => 'Ц',
'%u0427' => 'Ч',
'%u0428' => 'Ш',
'%u0429' => 'Щ',
'%u042A' => 'Ъ',
'%u042B' => 'Ы',
'%u042C' => 'Ь',
'%u042D' => 'Э',
'%u042E' => 'Ю',
'%u042F' => 'Я',
'%u0430' => 'а',
'%u0431' => 'б',
'%u0432' => 'в',
'%u0433' => 'г',
'%u0434' => 'д',
'%u0435' => 'е',
'%u0436' => 'ж',
'%u0437' => 'з',
'%u0438' => 'и',
'%u0439' => 'й',
'%u043A' => 'к',
'%u043B' => 'л',
'%u043C' => 'м',
'%u043D' => 'н',
'%u043E' => 'о',
'%u043F' => 'п',
'%u0440' => 'р',
'%u0441' => 'с',
'%u0442' => 'т',
'%u0443' => 'у',
'%u0444' => 'ф',
'%u0445' => 'х',
'%u0446' => 'ц',
'%u0447' => 'ч',
'%u0448' => 'ш',
'%u0449' => 'щ',
'%u044A' => 'ъ',
'%u044B' => 'ы',
'%u044C' => 'ь',
'%u044D' => 'э',
'%u044E' => 'ю',
'%u044F' => 'я',

'%u0451' => 'ё',

'%u2116' => '№',

# а этим я конвертил из iso8859

chr(208).chr(129) => 'Ё',

chr(208).chr(144) => 'А',
chr(208).chr(145) => 'Б',
chr(208).chr(146) => 'В',
chr(208).chr(147) => 'Г',
chr(208).chr(148) => 'Д',
chr(208).chr(149) => 'Е',
chr(208).chr(150) => 'Ж',
chr(208).chr(151) => 'З',
chr(208).chr(152) => 'И',
chr(208).chr(153) => 'Й',
chr(208).chr(154) => 'К',
chr(208).chr(155) => 'Л',
chr(208).chr(156) => 'М',
chr(208).chr(157) => 'Н',
chr(208).chr(158) => 'О',
chr(208).chr(159) => 'П',
chr(208).chr(160) => 'Р',
chr(208).chr(161) => 'С',
chr(208).chr(162) => 'Т',
chr(208).chr(163) => 'У',
chr(208).chr(164) => 'Ф',
chr(208).chr(165) => 'Х',
chr(208).chr(166) => 'Ц',
chr(208).chr(167) => 'Ч',
chr(208).chr(168) => 'Ш',
chr(208).chr(169) => 'Щ',
chr(208).chr(170) => 'Ъ',
chr(208).chr(171) => 'Ы',
chr(208).chr(172) => 'Ь',
chr(208).chr(173) => 'Э',
chr(208).chr(174) => 'Ю',
chr(208).chr(175) => 'Я',
chr(208).chr(176) => 'а',
chr(208).chr(177) => 'б',
chr(208).chr(178) => 'в',
chr(208).chr(179) => 'г',
chr(208).chr(180) => 'д',
chr(208).chr(181) => 'е',
chr(208).chr(182) => 'ж',
chr(208).chr(183) => 'з',
chr(208).chr(184) => 'и',
chr(208).chr(185) => 'й',
chr(208).chr(186) => 'к',
chr(208).chr(187) => 'л',
chr(208).chr(188) => 'м',
chr(208).chr(189) => 'н',
chr(208).chr(190) => 'о',
chr(208).chr(191) => 'п',

chr(209).chr(128) => 'р',
chr(209).chr(129) => 'с',
chr(209).chr(130) => 'т',
chr(209).chr(131) => 'у',
chr(209).chr(132) => 'ф',
chr(209).chr(133) => 'х',
chr(209).chr(134) => 'ц',
chr(209).chr(135) => 'ч',
chr(209).chr(136) => 'ш',
chr(209).chr(137) => 'щ',
chr(209).chr(138) => 'ъ',
chr(209).chr(139) => 'ы',
chr(209).chr(140) => 'ь',
chr(209).chr(141) => 'э',
chr(209).chr(142) => 'ю',
chr(209).chr(143) => 'я',

chr(209).chr(145) => 'ё',

'в„–' => '№',
# '&' => '&',
));
}

всё бы ничего, но
- пропадает символ '+' (плюс) - передается в виде пробела :(
- все-таки хотелось бы нечто универсальное для любого юникода - не только кирилистического - вычислять разницу в кодах символов разных кодировок, я так понял, глупо... этим уменьшится только количество строк php, а не логика

зы
без encode не могу - всё после символа & пропадает как новая переменная - как при методе get

Sham
25-12-2006, 20:56
VeshchiyOleg про локаль не забываем... setlocale(LC_ALL,"ru_RU.CP1251");

VeshchiyOleg
25-12-2006, 21:14
да я пробовал локаль прописывать в .htaccess - не помогло

а куда это засунуть???
в начало скрипта???
или можно непосредственно перед обращением к переменной???
и что делать, если текст пришел уже в виде %u0...???

Sham
25-12-2006, 22:07
VeshchiyOleg setlocale - ф-я PHP, соотв. лучше в начало скрипта (htaccess тут ни при делах). К тому же нужно уточнить имя локали в твоей системе (если локали системы и желаемая идентичны - передаем пустую строку). см. также тут (http://www.faqs.org/rfcs/rfc1766) и тут (http://www.w3.org/WAI/ER/IG/ert/iso639.htm)

VeshchiyOleg
26-12-2006, 10:28
setlocale после escape не помогает
setlocale вообще не помогает!!!
после отправки текста (без escape)
АБВГДЕЁЖЗИЙКЛМН
приходит
АБВГДЕЁЖЗР?ЙКЛМН
т.е. опять невесть в чем!!!

у меня возникла идея, как это сделать, но не хватает опыта:
после escape символы приходят в виде
%u0410 - (заглавное А на кирилице)
0410 - это не что иное как шестнадцатеричный код символа
т.е. если мы пересчитаем 0410 из шестнадцатеричного в десятичное число, то получим 1040
короче если привести
%u0410 к виду А
то мы получим не что иное, как нормальную html-сущность символа А на кирилице
а если после этого сделать еще и
html_entity_decode -- Преобразует HTML сущности в соответствующие символы
то на выходе должна появиться строка, которую вводили

вопрос КАК ЭТО СДЕЛАТЬ на php???

остается открытым вопрос:
как передавать плюсы с использованием encode???

Sham
26-12-2006, 16:07
VeshchiyOleg а как же rawurldecode()? Есть еще urldecode() но она afaik плюс в пробел декодит..

VeshchiyOleg
26-12-2006, 17:27
javascript:escape('АБВ') == '%u0410%u0411%u0412'
urldecode('%u0410%u0411%u0412') == '%u0410%u0411%u0412'
rawurldecode('%u0410%u0411%u0412') == '%u0410%u0411%u0412'

всё не то!!!

я тут сделал функцию
всё супер
с одним но...

html_entity_decode не работает как я думал

function global_decode(
$str
) {

return html_entity_decode(preg_replace_callback(
'|(?:%u.{4})|',
create_function(
'$matches',
'return \'&#\'.hexdec(substr($matches[0], 2)).\';\';'
),
$str
));
}

urldecode('%u0410%u0411%u0412') == 'АБВ'

на экране всё классно, но мне надо бы еще с текстом поработать прежде чем выводить

что делать дальше??? как перевести это в нормальные буквы???

Sham
26-12-2006, 22:42
VeshchiyOleghtml_entity_decode не работает как я думалв смысле? твоя ф-я не затронет небуквенные ASCII-символы, а посему без rawurldecode не обойтись...

VeshchiyOleg
27-12-2006, 15:09
rawurldecode

(PHP 3, PHP 4, PHP 5)
rawurldecode -- Decode URL-encoded strings
Description
string rawurldecode ( string str )

Returns a string in which the sequences with percent (%) signs followed by two hex digits have been replaced with literal characters. не та это функция!!!
джаваскриптовский escape приводит не к виду % и следом за ним две шестнадцатеричные цифры, а % потом u и потом ЧЕТЫРЕ шестнадцатеричные цифры!!!
а если не преобразовывать, то получается вообще какая-то абракадабра, которая никак не обрабатывается, кроме как заменой двух символов на один (см. первый пост вторую половину скрипта)
так что rawurldecode у меня ничего не меняет. ВООБЩЕ!!!

я тут стал копать глубже
оказывается, эта трабла возникает только при методе POST
при GET всё ок (без escape)

я использую для ajax`а библиотеку prototype.js v 1.4.0
там при POST отправляются следующие заголовки:

X-Requested-With:XMLHttpRequest
X-Prototype-Version:Prototype.Version
Content-type:application/x-www-form-urlencoded
Connection:close

потом собсна тело запроса

может тут собака порылась???
я уж в контент-тип и кодировку прописывал

читал статью http://phpclub.ru/detail/article/http_request
интересно, но вроде всё правильно...
за исключением того, что имитация POST`а какая-то кривая насчет русских символов :(

Sham
27-12-2006, 16:35
VeshchiyOlegescape приводит не к виду % и следом за ним две шестнадцатеричные цифры, а % потом u и потом ЧЕТЫРЕ шестнадцатеричные цифры!!! RTFM. К виду %uxxxx приводятся символы со значением больше 255, а к виду %xx приводятся небуквенные символы (типа пробелов, кавычек). Вот как раз для второго случая тебе и нужен rawurldecode (поскольку твоя ф-я затрагивает только первый случай)...

benya
27-12-2006, 16:59
iso8859-1 (в доках по php)

C чего вы взяли что она приходит в iso8859-1?
Насколько я помню в utf-8

VeshchiyOleg
27-12-2006, 17:56
1. а есть ли в javascript функция, которая переведет мне букву 'а' в '%D0%B0'???
ну и ВСЕ остальные буквы естессно (ну неужели нельзя обойтись без массива??? неужели нет четкого алгоритма???)

2. может есть в php функция, которая переведет 'А' в 'А'???
или тоже без массива не обойтись???

C чего вы взяли что она приходит в iso8859-1?
Насколько я помню в utf-8
с чего бы ей приходить в utf-8???
пусть в ней - мне все равно!!!
как ее перевести в удобоваримый текст средствами php???

Prisoner
27-12-2006, 21:31
Поглядите готовую реализацию (http://dklab.ru/wsvn/lib/trunk/lib/JsHttpRequest/JsHttpRequest.php), внимательно поглядывая комментарии. Метод JsHttpRequest::ucs2EntitiesDecode, имхо, то что Вам необходимо.

Sham
28-12-2006, 00:29
VeshchiyOleg у тебя уже каша в голове :)ну неужели нельзя обойтись без массива??? ты же сам предложил рабочую ф-ю с html_entity_decode... просто дополнительно (или предварительно) обработай строку с пом. rawurldecode и получишь готовую строку...есть в php функция, которая переведет 'А' в 'А'???есть такая партия, и Вы ее знаете :) html_entity_decode зовется :) Разберись там у себя, кофейку попей, валерьяночки... :)

VeshchiyOleg
28-12-2006, 09:15
html_entity_decode
символ А не переводит в А, а оставляет его без изменений - проверено - результат сравнения false, хотя на экране действительно выглядит похоже.
Метод JsHttpRequest::ucs2EntitiesDecode
/**
* Decode all %uXXXX entities in string or array (recurrent).
* String must not contain %XX entities - they are ignored!
*/
function _ucs2EntitiesDecode($data)
{
if (is_array($data)) {
$d = array();
foreach ($data as $k=>$v) {
$d[$this->_ucs2EntitiesDecode($k)] = $this->_ucs2EntitiesDecode($v);
}
return $d;
} else {
if (strpos($data, '%u') !== false) { // improve speed
$data = preg_replace_callback('/%u([0-9A-F]{1,4})/si', array(&$this, '_ucs2EntitiesDecodeCallback'), $data);
}
return $data;
}
}


/**
* Decode one %uXXXX entity (RE callback).
*/
function _ucs2EntitiesDecodeCallback($p)
{
$hex = $p[1];
$dec = hexdec($hex);
if ($dec === "38" && $this->SCRIPT_DECODE_MODE == 'entities') {
// Process "&" separately in "entities" decode mode.
$c = "&";
} else {
if (is_callable('iconv')) {
$c = @iconv('UCS-2BE', $this->SCRIPT_ENCODING, pack('n', $dec));
} else {
$c = $this->_decUcs2Decode($dec, $this->SCRIPT_ENCODING);
}
if (!strlen($c)) {
if ($this->SCRIPT_DECODE_MODE == 'entities') {
$c = '&#'.$dec.';';
} else {
$c = '?';
}
}
}
return $c;
}


/**
* If there is no ICONV, try to decode 1-byte characters manually
* (for most popular charsets only).
*/

/**
* Convert from UCS-2BE decimal to $toEnc.
*/
function _decUcs2Decode($code, $toEnc)
{
if ($code < 128) return chr($code);
if (isset($this->_encTables[$toEnc])) {
$p = array_search($code, $this->_encTables[$toEnc]);
if ($p !== false) return chr(128 + $p);
}
return "";
}


/**
* UCS-2BE -> 1-byte encodings (from #128).
*/
var $_encTables = array(
'windows-1251' => array(
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0098, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
),
'koi8-r' => array(
0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255d, 0x255E,
0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043d, 0x043E,
0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
0x044C, 0x044B, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044A,
0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041d, 0x041E,
0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
0x042C, 0x042B, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042A
),
);

всё просто супер, но, если у нас нет iconv мы опять-таки упираемся в массив

for most popular charsets onlyключевое слово здесь only IMHO
а если это немец и он по-немецки пишет??? его каракули не переведутся и съедут в крякозяблы!!!

Sham
28-12-2006, 18:06
VeshchiyOleg ты меня удивляешь...
вставь этот код, и посмотри, что получится... :)
if (html_entity_decode("&amp;#1040;", ENT_QUOTES, "cp1251")=="А") {
echo "Это видимо я такой суетливый, рассеяный и невнимательный,<br />";
echo "и мне еще надо научиться таки внимательно читать мануалы<br />";
echo "к языкам программирования... :)";
}

VeshchiyOleg
29-12-2006, 01:21
гыыы
написало... :)))

VeshchiyOleg
29-12-2006, 01:45
, ENT_QUOTES, "cp1251"
оказывается, дело было в этих двух параметрах!!!
итого функция принимает вид
function decode_from_js_escape(
$str
) {
return html_entity_decode(preg_replace_callback(
'|(?:%u.{4})|',
create_function(
'$matches',
'return \'&#\'.hexdec(substr($matches[0], 2)).\';\';'
),
$str
), ENT_QUOTES, 'cp1251');
}
спасибо

Sham
29-12-2006, 20:46
VeshchiyOleg, а где rawurldecode? Чем будешь пробелы и пр. небуквенные символы (%хх) раскодировать?




© OSzone.net 2001-2012