Какие символы заменяются на %хх при HTTP запросе? Знаю, что пробел - %20, Русские буквы - %hex-код. А что с остальным? Иероглифы, ?, $, &... Заранее спасибо.
Читайте rfc3986 (или предыдущую версию - rfc1738). Если вкратце, то не заменяются следующие символы (unreserved characters): Зарезервированные символы (reserved characters) - заменяются, если не используются по назначению. Всё остальное заменяется. Иероглифы сводятся к двухбайтной кодировке, либо к UTF-8 и, естественно, тоже заменяются.
А как определить, UTF-8 (2 байта на символ - следовательно 2 процента) передано или ASCII кодировка (1 байт) ??
Нашёл кусок кода: Код (Text): private static String unescape(String s) { StringBuffer sbuf = new StringBuffer () ; int l = s.length() ; int ch = -1 ; int b, sumb = 0; for (int i = 0, more = -1 ; i < l ; i++) { /* Get next byte b from URL segment s */ switch (ch = s.charAt(i)) { case '%': ch = s.charAt (++i) ; int hb = (Character.isDigit ((char) ch) ? ch - '0' : 10+Character.toLowerCase((char) ch) - 'a') & 0xF ; ch = s.charAt (++i) ; int lb = (Character.isDigit ((char) ch) ? ch - '0' : 10+Character.toLowerCase ((char) ch)-'a') & 0xF ; b = (hb << 4) | lb ; break ; case '+': b = ' ' ; break ; default: b = ch ; } /* Decode byte b as UTF-8, sumb collects incomplete chars */ if ((b & 0xc0) == 0x80) { // 10xxxxxx (continuation byte) sumb = (sumb << 6) | (b & 0x3f) ; // Add 6 bits to sumb if (--more == 0) sbuf.append((char) sumb) ; // Add char to sbuf } else if ((b & 0x80) == 0x00) { // 0xxxxxxx (yields 7 bits) sbuf.append((char) b) ; // Store in sbuf } else if ((b & 0xe0) == 0xc0) { // 110xxxxx (yields 5 bits) sumb = b & 0x1f; more = 1; // Expect 1 more byte } else if ((b & 0xf0) == 0xe0) { // 1110xxxx (yields 4 bits) sumb = b & 0x0f; more = 2; // Expect 2 more bytes } else if ((b & 0xf8) == 0xf0) { // 11110xxx (yields 3 bits) sumb = b & 0x07; more = 3; // Expect 3 more bytes } else if ((b & 0xfc) == 0xf8) { // 111110xx (yields 2 bits) sumb = b & 0x03; more = 4; // Expect 4 more bytes } else /*if ((b & 0xfe) == 0xfc)*/ { // 1111110x (yields 1 bit) sumb = b & 0x01; more = 5; // Expect 5 more bytes } /* We don't test if the UTF-8 encoding is well-formed */ } return sbuf.toString() ; } Понял, что '+' = ' ', '%..' перекодируются в спецсимволы при декодировании, остальные остаются без изменения. А вот какие коды нужно распознавать как Unicode, а какие - как ASCII - непонятно. (я в java не силён.)
Вообщем, разобрался. Есть такой код перекодировки. Может, кто-нибудь проверит на оптимальность.. Код (Text): DecodeURI proc USES EDI ESI, lpBuffer:DWORD ; eax = length of res, enc_string ends with 0x0 MOV EDI, lpBuffer MOV ESI, EDI @Loop: LODSB CMP AL, '%' JNE @Save LODSW ; Work with AH CMP AH, 'A' JB A1 CMP AH, 'a' JB A2 ADD AH, -('a'-10) JMP A3 A2: ADD AH, -('A'-10) JMP A3 A1: XOR AH, 30h A3: ; Work with AL CMP AL, 'A' JB B1 CMP AL, 'a' JB B2 ADD AL, -('a'-10) JMP B3 B2: ADD AL, -('A'-10) JMP B3 B1: XOR AL, 30h B3: SHL AL, 4 OR AL, AH @Save: STOSB CMP AL, 0 JNE @Loop SUB ESI, lpBuffer DEC ESI ADD ESP, -(MAX_PATH*2) MOV EDI, ESP INVOKE MultiByteToWideChar, CP_UTF8, 0, lpBuffer, ESI, EDI, MAX_PATH*2 INVOKE WideCharToMultiByte, 1251, 0, EDI, EAX, lpBuffer, MAX_PATH, NULL, NULL ADD ESP, (MAX_PATH*2) MOV EDI, lpBuffer MOV BYTE PTR [EDI+EAX], 0 RET DecodeURI Endp
>А как определить, UTF-8 (2 байта на символ - следовательно 2 процента) во первых не два байта а от 2-х до 6. во вторых http://ru.wikipedia.org/wiki/UTF-8 оба товоих вопроса есть в википедии, которая раскрывается по первой сылке на запросы utf-8 и url. конечно лучше зафлудить форум еше одной говнотемой. чем зайти в гуглю. и я уверен что на твой третий вопрос тоже юудет ответ в гугле по первой ссылке.
>это utf-8 от 2х до шести? вообще-то латинский алфавит кодируется 8 битами. имелось ввиду кодированые символы, а так да верное замечение.
djmans, А разве по коду не видно, что я это давно понял?! Тем более, что флудить я не собираюсь, не собирался и не буду собираться! Проблема уже решена, хоть и немного корявым способом. Если кто-нибудь поможет оптимизировать преведённый выше код, скажу спасибо, если нет - тему можно закрывать. В коде идёт перекодировка имени файла (можно и всего URI) из URI ('%' + UTF8) в utf8.
DecodeURI proc USES EDI ESI, lpBufferWORD ; eax = length of res, enc_string ends with 0x0 MOV EDI, lpBuffer MOV ESI, EDI ; Избавляемся от процентов в адресе, подменяя их коды на истинные значения байтов. ; Может быть, есть способ короче.. @Loop: LODSB CMP AL, '%' JNE @Save LODSW ; Work with AH CMP AH, 'A' JB A1 CMP AH, 'a' JB A2 ADD AH, -('a'-10) JMP A3 A2: ADD AH, -('A'-10) JMP A3 A1: XOR AH, 30h A3: ; Work with AL CMP AL, 'A' JB B1 CMP AL, 'a' JB B2 ADD AL, -('a'-10) JMP B3 B2: ADD AL, -('A'-10) JMP B3 B1: XOR AL, 30h B3: SHL AL, 4 OR AL, AH @Save: STOSB CMP AL, 0 JNE @Loop ; Получаем размер строки SUB ESI, lpBuffer DEC ESI ; Далее декодируем функциями Windows'а ADD ESP, -(MAX_PATH*2) MOV EDI, ESP INVOKE MultiByteToWideChar, CP_UTF8, 0, lpBuffer, ESI, EDI, MAX_PATH*2 INVOKE WideCharToMultiByte, 1251, 0, EDI, EAX, lpBuffer, MAX_PATH, NULL, NULL ADD ESP, (MAX_PATH*2) MOV EDI, lpBuffer MOV BYTE PTR [EDI+EAX], 0 RET DecodeURI Endp