Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Вебмастеру (http://forum.oszone.net/forumdisplay.php?f=22)
-   -   [решено] декодирование в php после javascript:encode (http://forum.oszone.net/showthread.php?t=76695)

VeshchiyOleg 25-12-2006 17:42 528985

декодирование в php после javascript:encode
 
при передаче данных в XMLHTTPRequest из javascript русские символы из кодировки 1251 приходят в php в некоей кодировке, которую называют iso8859-1 (в доках по php), хотя на самом деле русские символы присутствуют только в iso8859-5. может это и одно и то же, однако обратно они приходят в ней же, а нифига не в 1251. iconv и прочие конверторы использовать не имею ни желания ни возможности - на локальной машине их нет, а я добавлять чего-либо не умею и не надо меня этому учить. а на сервере и играться как-то кощунственно и туда тоже надо доставлять дополнительные расширения. потом... возможно ведь и использование пользователями других символов, которые не будут входить уже в iso8859-5. следовательно перед отправкой я делаю строке encode в javascript`е. все символы (русские) приходят в виде %u0... для их переконвертации я написал свой обработчик:
PHP код:

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 529051

VeshchiyOleg про локаль не забываем...
PHP код:

setlocale(LC_ALL,"ru_RU.CP1251"); 


VeshchiyOleg 25-12-2006 21:14 529063

да я пробовал локаль прописывать в .htaccess - не помогло

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

Sham 25-12-2006 22:07 529079

VeshchiyOleg setlocale - ф-я PHP, соотв. лучше в начало скрипта (htaccess тут ни при делах). К тому же нужно уточнить имя локали в твоей системе (если локали системы и желаемая идентичны - передаем пустую строку). см. также тут и тут

VeshchiyOleg 26-12-2006 10:28 529214

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

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

html_entity_decode -- Преобразует HTML сущности в соответствующие символы
то на выходе должна появиться строка, которую вводили

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

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

Sham 26-12-2006 16:07 529342

VeshchiyOleg а как же rawurldecode()? Есть еще urldecode() но она afaik плюс в пробел декодит..

VeshchiyOleg 26-12-2006 17:27 529372

javascript:escape('АБВ') == '%u0410%u0411%u0412'
urldecode('%u0410%u0411%u0412') == '%u0410%u0411%u0412'
rawurldecode('%u0410%u0411%u0412') == '%u0410%u0411%u0412'

всё не то!!!

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

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

PHP код:

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 529487

VeshchiyOleg
Цитата:

html_entity_decode не работает как я думал
в смысле? твоя ф-я не затронет небуквенные ASCII-символы, а посему без rawurldecode не обойтись...

VeshchiyOleg 27-12-2006 15:09 529776

Цитата:

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 529814

VeshchiyOleg
Цитата:

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

benya 27-12-2006 16:59 529825

Цитата:

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

VeshchiyOleg 27-12-2006 17:56 529840

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

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

Цитата:

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

Prisoner 27-12-2006 21:31 529908

Поглядите готовую реализацию, внимательно поглядывая комментарии. Метод JsHttpRequest::ucs2EntitiesDecode, имхо, то что Вам необходимо.

Sham 28-12-2006 00:29 529967

VeshchiyOleg у тебя уже каша в голове :)
Цитата:

ну неужели нельзя обойтись без массива???
ты же сам предложил рабочую ф-ю с html_entity_decode... просто дополнительно (или предварительно) обработай строку с пом. rawurldecode и получишь готовую строку...
Цитата:

есть в php функция, которая переведет 'А' в 'А'???
есть такая партия, и Вы ее знаете :) html_entity_decode зовется :) Разберись там у себя, кофейку попей, валерьяночки... :)

VeshchiyOleg 28-12-2006 09:15 530042

Цитата:

html_entity_decode
символ А не переводит в А, а оставляет его без изменений - проверено - результат сравнения false, хотя на экране действительно выглядит похоже.
Цитата:

Метод JsHttpRequest::ucs2EntitiesDecode
PHP код:

/** 
     * 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_ENCODINGpack('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( 
            
0x04020x04030x201A0x04530x201E0x20260x20200x2021
            
0x20AC0x20300x04090x20390x040A0x040C0x040B0x040F
            
0x04520x20180x20190x201C0x201D0x20220x20130x2014
            
0x00980x21220x04590x203A0x045A0x045C0x045B0x045F
            
0x00A00x040E0x045E0x04080x00A40x04900x00A60x00A7
            
0x04010x00A90x04040x00AB0x00AC0x00AD0x00AE0x0407
            
0x00B00x00B10x04060x04560x04910x00B50x00B60x00B7
            
0x04510x21160x04540x00BB0x04580x04050x04550x0457
            
0x04100x04110x04120x04130x04140x04150x04160x0417
            
0x04180x04190x041A0x041B0x041C0x041D0x041E0x041F
            
0x04200x04210x04220x04230x04240x04250x04260x0427
            
0x04280x04290x042A0x042B0x042C0x042D0x042E0x042F
            
0x04300x04310x04320x04330x04340x04350x04360x0437
            
0x04380x04390x043A0x043B0x043C0x043D0x043E0x043F
            
0x04400x04410x04420x04430x04440x04450x04460x0447
            
0x04480x04490x044A0x044B0x044C0x044D0x044E0x044F
        ), 
        
'koi8-r' => array( 
            
0x25000x25020x250C0x25100x25140x25180x251C0x2524
            
0x252C0x25340x253C0x25800x25840x25880x258C0x2590
            
0x25910x25920x25930x23200x25A00x22190x221A0x2248
            
0x22640x22650x00A00x23210x00B00x00B20x00B70x00F7
            
0x25500x25510x25520x04510x25530x25540x25550x2556
            
0x25570x25580x25590x255A0x255B0x255C0x255d0x255E
            
0x255F0x25600x25610x04010x25620x25630x25640x2565
            
0x25660x25670x25680x25690x256A0x256B0x256C0x00A9
            
0x044E0x04300x04310x04460x04340x04350x04440x0433
            
0x04450x04380x04390x043A0x043B0x043C0x043d0x043E
            
0x043F0x044F0x04400x04410x04420x04430x04360x0432
            
0x044C0x044B0x04370x04480x044d0x04490x04470x044A
            
0x042E0x04100x04110x04260x04140x04150x04240x0413
            
0x04250x04180x04190x041A0x041B0x041C0x041d0x041E
            
0x041F0x042F0x04200x04210x04220x04230x04160x0412
            
0x042C0x042B0x04170x04280x042d0x04290x04270x042A       
        
), 
    ); 

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

Цитата:

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

Sham 28-12-2006 18:06 530195

VeshchiyOleg ты меня удивляешь...
вставь этот код, и посмотри, что получится... :)
PHP код:

if (html_entity_decode("А"ENT_QUOTES"cp1251")=="А") {
echo 
"Это видимо я такой суетливый, рассеяный и невнимательный,<br />";
echo 
"и мне еще надо научиться таки внимательно читать мануалы<br />";
echo 
"к языкам программирования... :)";



VeshchiyOleg 29-12-2006 01:21 530283

гыыы
написало... :)))

VeshchiyOleg 29-12-2006 01:45 530285

Цитата:

, ENT_QUOTES, "cp1251"
оказывается, дело было в этих двух параметрах!!!
итого функция принимает вид
PHP код:

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 530575

VeshchiyOleg, а где rawurldecode? Чем будешь пробелы и пр. небуквенные символы (%хх) раскодировать?


Время: 08:13.

Время: 08:13.
© OSzone.net 2001-