Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.10.11;
Скачать: CL | DM;

Вниз

URL-кодировка (URL encoding, Percent-encoding)   Найти похожие ветки 

 
TIF ©   (2009-07-28 15:51) [0]

Меня заело :-( Не могу никак понять одну вещь
Программа получает из браузера ссылку. Всё бы хорошо, но только IE (люблю Microsoft :) передаёт ссылку "как есть", остальные браузеры применяют к ней URL-кодирование. Опять же, всё бы хорошо, но! Firefox кодирует каждый символ двумя байтами, Opera  и Chrome - одним:

IE
[AbCdEfАбВгДе]
Opera
[AbCdEf%C0%E1%C2%E3%C4%E5]
Chrome
%5BAbCdEf%C0%E1%C2%E3%C4%E5%5D
Fx
[AbCdEf%D0%90%D0%B1%D0%92%D0%B3%D0%94%D0%B5]


А теперь и вопрос, на котором меня заело: как определить, что %D0%90 - это именно ОДИН символ, а не два? %-\

PS: возможности определить, какой браузер передал ссылку нет


 
Lamer@fools.ua ©   (2009-07-28 15:55) [1]

В заголовке запроса кодировка УРЛа должна передаваться, вроде...


 
TIF ©   (2009-07-28 15:57) [2]

> В заголовке запроса

Нет никакого заголовка. В наличии только ссылка...


 
clickmaker ©   (2009-07-28 16:07) [3]

> Программа получает из браузера ссылку

из адресной строки? IE 7 на английской винде кодирует так: AbCdEf%c0%e1%c2%e3%c4%e5


 
Anatoly Podgoretsky ©   (2009-07-28 16:07) [4]

Тогда ни как, кроме методом проб и ошибок. Но зато вариантов всего лишь два.

И предположение насчет браузеров, кто как кодирует в принципе неверное.


 
TIF ©   (2009-07-28 16:18) [5]

> из адресной строки?

Нет. Pluggable protocol

> Anatoly Podgoretsky ©   (28.07.09 16:07) [4]
> Тогда никак, кроме методом проб и ошибок

Ну есть конечно вариант, внедрить в ссылку в заранее определенное место пару буковок и анализировать их, но хочется простое решение, должно же оно быть...
У меня мысли крутятся вокруг UTF-8:
Текст, состоящий только из символов с номером меньше 128, при записи в UTF-8 превращается в обычный текст ASCII. И наоборот, в тексте UTF-8 любой байт со значением меньше 128 изображает символ ASCII с тем же кодом.
Тут похожая ситуация. Только провести параллели бы какие-то...


 
Anatoly Podgoretsky ©   (2009-07-28 16:52) [6]

Никаких паралелей, один и тот же текст "AbCdEf%D0%90" может быть как OEM, так и ANSI, так и UTF-8


 
clickmaker ©   (2009-07-28 16:59) [7]

а программа на дельфи?
я бы погуглил по словам UrlDecode Delphi


 
Anatoly Podgoretsky ©   (2009-07-28 17:01) [8]

> clickmaker  (28.07.2009 16:59:07)  [7]

Без знания кодировки это мало чем поможет.


 
antonn ©   (2009-07-28 17:02) [9]


> Никаких паралелей, один и тот же текст "AbCdEf%D0%90" может
> быть как OEM, так и ANSI, так и UTF-8

AbCdEf%D0%90 только в UTF читаем как обычный текст.


> TIF ©   (28.07.09 15:51)

ищи %D0 и смотри парные ему, он в UTF есть


 
Noctis   (2009-07-28 17:08) [10]

Строку, требующую раскодирования можно отличить от строки, не требующей раскодирования наличием в ней паттерна, удовлетворяющего регулярному выражению %\w{2}.
После преобразования последовательностей кодов в байты наличие UTF-8 с большой вероятностью можно определить соответствием последовательностей байтов в строке следующим паттернам (см. RFC utf-8).

  Char. number range  |        UTF-8 octet sequence
     (hexadecimal)    |              (binary)
  --------------------+---------------------------------------------
  0000 0000-0000 007F | 0xxxxxxx
  0000 0080-0000 07FF | 110xxxxx 10xxxxxx
  0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
  0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx


 
TIF ©   (2009-07-28 17:35) [11]

> я бы погуглил по словам UrlDecode Delphi

Уже скачал несколько URLEncode и URLDecode функций, но самое весёлое, что они не работают в D2009 (дополнительные проблемы с кодировкой лезут)...


 
Anatoly Podgoretsky ©   (2009-07-28 19:02) [12]


> AbCdEf%D0%90 только в UTF читаем как обычный текст.

Он отлично читается - это русская буква Р и вторая казахская буква, как известно у казахов таже кодовая страницы, только расширеная. Кроме того я взял первую попавшию последовательность, можно взять и другую.


 
Anatoly Podgoretsky ©   (2009-07-28 19:05) [13]


> Уже скачал несколько URLEncode и URLDecode функций, но самое
> весёлое, что они не работают в D2009 (дополнительные проблемы
> с кодировкой

Ты зря это делал, string в 2009 UnicodeString, а не AnsiString.
Надо использовать из 2009 или особый формат вызова и определение переменных.
Одна из ошибок Д2009 - это то что они перестарались с переводом на UnicodeString, перевели больше чем надо, пострадали Indy и IB, и наверно еще ряд сетевых функций.


 
Пит   (2009-07-29 13:30) [14]

Я уже поднимал ветку по этому поводу.

Да, это URL кодирование (через проценты), в одном случае кодируеся win-1251, в другом случае unicode (поэтому два байта на символ).

В общем случае определить невозможно формат. Но есть способы догадаться. Даже в windows API вроде есть встроенная функция, которая с определенной вероятностью пытается определить набор символов, ANSI или Wide. Не помню как называется, в Рихтере есть.

Например, Гугл это делает достаточно хорошо. Кодировки разные:

- win-1251
http://www.google.ru/search?hl=ru&q=%EF%F0%E8%E2%E5%F2

- unicode
http://www.google.ru/search?hl=ru&q=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

а результат одинаковый.


 
clickmaker ©   (2009-07-29 13:39) [15]

> в windows API вроде есть встроенная функция

IsTextUnicode


 
Anatoly Podgoretsky ©   (2009-07-29 13:40) [16]

> Пит  (29.07.2009 13:30:14)  [14]

Попробуй изменить %D0%BF на %D0%01 и посмотри на результат
Гугл обладает излишней информацией и плюс проверяет по словарю.


 
Anatoly Podgoretsky ©   (2009-07-29 13:44) [17]

Заодно можешь провести тоже и для ANSI может даже нагляднее будет.


 
Пит   (2009-07-29 17:56) [18]

А к чему вы это говорите? Тон как будто опровергаете, а смысл как будто подтверждаете.

Естественно, это косвенные методы определения, точно также как и у IsTextUnicode. Ясно было сказано:

>В общем случае определить невозможно формат


 
blackman ©   (2009-07-29 20:06) [19]

См.<meta http-equiv="Content-Type" content="text/html; charset... - страницы
См. функции
Unit: IdGlobal
URLDecode(AnsiToUtf8("привет")) //"%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82"
URLDecode("привет") //"%CF%F0%E8%E2%E5%F2%2E"

или HTTPEncode(AnsiToUtf8(...

function HTTPEncode(const AStr: string): string;
const
  NoConversion = ["A".."Z", "a".."z", "*", "@", ".", "_", "-"];
var
  Sp, Rp: PChar;
begin
  SetLength(Result, Length(AStr) * 3);
  Sp := PChar(AStr);
  Rp := PChar(Result);
  while Sp^ <> #0 do
  begin
    if Sp^ in NoConversion then
      Rp^ := Sp^
    else if Sp^ = " " then
      Rp^ := "+"
    else
    begin
      FormatBuf(Rp^, 3, "%%%.2x", 6, [Ord(Sp^)]);
      Inc(Rp, 2);
    end;
    Inc(Rp);
    Inc(Sp);
  end;
  SetLength(Result, Rp - PChar(Result));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text := HTTPEncode(Edit1.Text);
end;
http://www.swissdelphicenter.ch/

Кроме того на этом сайте тоже кое что есть
http://www.delphimaster.ru/books/978594723593/fragment.html


 
Piter ©   (2009-07-29 22:24) [20]

blackman ©   (29.07.09 20:06) [19]

по-моему, ты нифига не въехал в квалификацию автора вопроса и в то, что он собственно хочет.

Вопрос не в том, откуда это взялось, с самого начала вроде автор дал понять, что он прекрасно понимает, что есть ANSI, а есть unicode.

Вопрос в том, как определить по известному GET-параметру в какой кодировке представлены данные. И ответ не раз дан опять же в этой ветке - никак. Можно только предполагать с той или иной точностью.


 
Anatoly Podgoretsky ©   (2009-07-29 23:01) [21]

> Piter  (29.07.2009 22:24:20)  [20]

При том определить не с помощью Гугловеба, а автономно, Гугловеб вносит искажения в процесс определения, поскольку добавляется информация о локальной кодировке компьютера. Наиболее качественное решение в [10] вероятность будет высокая и пропорциональна длине ссылке. Надо только учесть, что не все символы в диапазоне 00-7F выводятся указаным кодом, по правилам на URI их тоже надо экранировать, но уже однобайтным кодом. Список этих кодов также есть в RFC и также особенность вывода пробелов, они заменяются по другой схеме.

Короче за эти годы очень намудрили. Из приведеных, только Chrome соответствует RFC для ANSI и наверно он также правильно работает с UTF. Кроме того тут еще отсутствует вариант с Unicode - %u####


 
TIF ©   (2009-07-30 00:04) [22]

> Piter ©   (29.07.09 22:24) [20]
> blackman ©   (29.07.09 20:06) [19]по-моему, ты нифига не
> въехал в квалификацию автора вопроса и в то, что он собственно
> хочет.

+1 :)

Anatoly Podgoretsky ©   (29.07.09 23:01) [21]
> Наиболее качественное решение в [10] вероятность будет высокая
> и пропорциональна длине ссылке.

Наверное в скором времени доведу до ума это распознавание, хоть оно и не идеальное, но пока всё-таки решил не мучаться и внедрять в начало ссылки короткое слово кириллицей (какой-нибудь маленький предлог, чтоб хоть со смыслом смотрелся, что-то вроде "Open?Для=http://") и ориентироваться по нему

> Из приведеных, только Chrome соответствует RFC для ANSI


Ох, не знаю. Покопался с хромом - вообще какой-то извращённый браузер :-( Создан на движке WebKit, но содержит куча странных отличий от Safari. Сафари, например, не приводит ссылку к нижнему регистру, а Chrome приводит, Сафари [ и ] в %-кодировку не переводит, а Chromt переводит

Сколько браузеров - столько и проблем :) Что и требовалось доказать


 
Anatoly Podgoretsky ©   (2009-07-30 09:38) [23]

> TIF  (30.07.2009 00:04:22)  [22]

Я не знаю, насколько извращен, я просто вижу по приведеным ссылкам


 
Anatoly Podgoretsky ©   (2009-07-30 09:42) [24]

> TIF  (30.07.2009 00:04:22)  [22]

> Ох, не знаю. Покопался с хромом - вообще какой-то извращённый браузер :-( Создан на движке WebKit, но содержит куча странных отличий от Safari. Сафари, например, не приводит ссылку к нижнему регистру, а Chrome приводит, Сафари [ и ] в %-кодировку не переводит, а Chromt переводит

Приведение к нижнему регистру, идиотичние не придумать, это же полный капец. Наверно у них там в Гугле все в нижнем регистре, вот и думают, что у других также.

ЗЫ: как на самом деле я не знаю.

Кстати я бы не стал делать вывод, насчет ИЕ, что мол он посылает как есть, этот браузер много хитрее.


 
TIF ©   (2009-08-06 20:18) [25]

> как определить, что %D0%90 - это именно ОДИН символ, а не
> два?

Отлично :) С поставленной задачей я всё-таки справился, даже добился большего, чем хотел.

В результате мучений и размышлений родилась функция URLDecode. На входе - строка в однобайтной или многобайтной (2-4 байта) URL-кодировке, на выходе - расшифрованный текст

Хотя я на это и не рассчитывал, но если этой функции скормить мешанину (один символ зашифрован с использованием одного байта на символ, а другой - двумя, тремя, а то и четырьмя), то на выходе также получаем расшифрованный текст!
Здесь всё благодаря "UTF-8 octet sequence (binary)" из RFC для UTF-8, то что давалось Noctis-ом в [10]:
> После преобразования последовательностей кодов в байты наличие
> UTF-8 с большой вероятностью можно определить соответствием
> последовательностей байтов в строке следующим паттернам
> (см. RFC utf-8).

Только работает это и без вычисления вероятностей. А вот у поисковиков не работает :) Яндекс с Google преобразуют мешашину "жёстко", а Bing просто игнорирует "однобайтные символы" с кодами > 128

http://yandex.ru/yandsearch?text=%EE%EF%F6%E8%E8+%D0%BE%D0%BF%D1%86%D0%B8%D0%B8%E2%82%AC
http://www.google.com/search?q=%EE%EF%F6%E8%E8+%D0%BE%D0%BF%D1%86%D0%B8%D0%B8%E2%82%AC
http://www.bing.com/search?q=%EE%EF%F6%E8%E8+%D0%BE%D0%BF%D1%86%D0%B8%D0%B8%E2%82%AC

Для полной уверенности прогнал функцию ещё по нескольким тестам, она их прошла успешно:
AbCdEf%D0%90%E2%82%AC

%EE%EF%F6%E8%E8%E2%82%AC
%D0%BE%D0%BF%D1%86%D0%B8%D0%B8%E2%82%AC
%EE%EF%F6%E8%E8+%D0%BE%D0%BF%D1%86%D0%B8%D0%B8%E2%82%AC
%D0%BE%D0%BF%D1%86%D0%B8%D0%B8+%EE%EF%F6%E8%E8%E2%82%AC

%d2%e5%f1%f2%ee%e2%e0%ff%20%f1%f1%fb%eb%ea%e0
%d0%a2%d0%b5%d1%81%d1%82%d0%be%d0%b2%d0%b0%d1%8f%20%d1%81%d1%81%d1%8b%d0%bb%d0%ba%d0%b0
%d2%e5%f1%f2%ee%e2%e0%ff%20%f1%f1%fb%eb%ea%e0+%d0%a2%d0%b5%d1%81%d1%82%d0%be%d0%b2%d0%b0%d1%8f%20%d1%81%d1%81%d1%8b%d0%bb%d0%ba%d0%b0
%d0%a2%d0%b5%d1%81%d1%82%d0%be%d0%b2%d0%b0%d1%8f%20%d1%81%d1%81%d1%8b%d0%bb%d0%ba%d0%b0+%d2%e5%f1%f2%ee%e2%e0%ff%20%f1%f1%fb%eb%ea%e0

add%c0%e4ress%f0%e5%f1
add%d0%90%d0%b4ress%d1%80%d0%b5%d1%81
add%c0%e4ress%f0%e5%f1+add%d0%90%d0%b4ress%d1%80%d0%b5%d1%81
add%d0%90%d0%b4ress%d1%80%d0%b5%d1%81+add%c0%e4ress%f0%e5%f1

%5BAbCdEf%C0%E1%C2%E3%C4%E5%5D
[AbCdEf%D0%90%D0%B1%D0%92%D0%B3%D0%94%D0%B5]
%5BAbCdEf%C0%E1%C2%E3%C4%E5%5D+[AbCdEf%D0%90%D0%B1%D0%92%D0%B3%D0%94%D0%B5]
[AbCdEf%D0%90%D0%B1%D0%92%D0%B3%D0%94%D0%B5]+%5BAbCdEf%C0%E1%C2%E3%C4%E5%5D

%D0%BE%EE%D0%BF%EF%D1%86%F6%D0%B8%E8%D0%B8%E8
%EE%D0%BE%EF%D0%BF%F6%D1%86%E8%D0%B8%E8%D0%B8

= = = = = = = = = =

AbCdEfА€

опции€
опции€
опции опции€
опции опции€

Тестовая ссылка
Тестовая ссылка
Тестовая ссылка Тестовая ссылка
Тестовая ссылка Тестовая ссылка

addАдressрес
addАдressрес
addАдressрес addАдressрес
addАдressрес addАдressрес

[AbCdEfАбВгДе]
[AbCdEfАбВгДе]
[AbCdEfАбВгДе] [AbCdEfАбВгДе]
[AbCdEfАбВгДе] [AbCdEfАбВгДе]

ооппццииии
ооппццииии


 
Piter ©   (2009-08-07 21:46) [26]

TIF ©   (06.08.09 20:18) [25]
Только работает это и без вычисления вероятностей


не пиши фигни. Способ предложенный Noctis"ом лишь один из способов. Который тоже может ошибиться, особенно если его применять как универсальный для ВСЕХ языков.

TIF ©   (06.08.09 20:18) [25]
Яндекс с Google преобразуют мешашину "жёстко",


и это правильно. Строка может быть ANSI, может быть Unicode, но она никак не может быть смешанной, это против всех стандартов.


 
TIF ©   (2009-08-08 00:12) [27]

> это против всех стандартов.

В IT самое интересное - это стандарты. Как часто они появляются, так часто их и нарушают. Так что иногда приходится приспосабливаться к самому неожиданному

> Способ предложенный Noctis"ом лишь один из способов

А я о чём, собственно? :) О своём способе. Об одном из множества (хотя все способы будут во многом похожими). Я в нём обошёлся без вероятностей.
Но! В рамках поставленной передо мной задачи созданный алгоритм работает: поедает закодированную %-ами ссылку (хоть ANSI, хоть Unicode), а выдаёт правильный результат.

Да. Браузеры не будут смешивать ANSI и Unicode, но "мешанина" - это всего лишь интересная особенность алгоритма и она позволит уменьшить размер закодированной строки если заранее известно, с какой кодовой страницей будем работать.

PS: чуть не забыл. Оформлю функцию, чтобы выглядела более-менее прилично, и выложу сюда


 
Piter ©   (2009-08-08 11:20) [28]

TIF ©   (08.08.09 0:12) [27]
Так что иногда приходится приспосабливаться к самому неожиданному


ну так приспособь еще к тому, что вдруг данные в URL закодированы XOR"ом по паролю, брутфорс хотя бы встрой... Остальое комментировать просто лень, ходьба по кругу.


 
TIF ©   (2009-08-10 07:09) [29]

> Оформлю функцию, чтобы выглядела более-менее прилично, и
> выложу сюда

И выложу сюда ссылку :)

http://InfoDelphi.ru/IDLib/URLDecode



Страницы: 1 вся ветка

Текущий архив: 2009.10.11;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.014 c
15-1250080125
desc
2009-08-12 16:28
2009.10.11
Принтер HP Officejet K7100 Series, печатает цветные полосы,


2-1249977509
Foster14
2009-08-11 11:58
2009.10.11
Работа с БД IB


15-1249590603
Юрий
2009-08-07 00:30
2009.10.11
С днем рождения ! 7 августа 2009 пятница


15-1249611810
Наиль
2009-08-07 06:23
2009.10.11
Embarcadero хвастается


15-1249924835
@!!ex
2009-08-10 21:20
2009.10.11
Где найти книг во вселенной BattleTech?