Декодирование URL

Иногда бывает нужно декодировать строку вида "c:documents%20and%20settings" в удобочитаемый текст. Можно, конечно, заменить все "%20" на пробелы, и считать что задача решена. А если в строке закодированы подобным образом не только пробелы? Если на входе попался URL с кучей подобных "процентов"?

Данная функция сделает правильное декодирование подобной строки.

Кому интересна теория — см. RFC 2396 часть 2

Собственно код:

Функция Из16ВЧисло(Знач Значение)

    Результат = 0;
   
Множитель = 1;
    Пока
Значение <> «» Цикл
       
Результат = Результат + Множитель * (Найти(«0123456789ABCDEF», Прав(Значение,1))-1);
       
Множитель = Множитель * 16;
       
Значение = Лев(Значение,СтрДлина(Значение)-1);
    КонецЦикла;
    Возврат
Результат;

КонецФункции

Функция ДекодироватьURL(URL, WindowsFileURI=Истина)

    ДлинаСтроки = СтрДлина(URL);
   
Инд = 1;
   
Результат = «»;
   
ПолныйКод = 0;
   
ОсталосьСимволов = 0;

    Пока Инд <= ДлинаСтроки Цикл

        Код = КодСимвола(URL, Инд);

        Если Код = 37 Тогда
           
// Символ(37) = «%»
           
Код = Из16ВЧисло(Сред(URL, Инд+1, 2));
           
Инд = Инд + 2;
        ИначеЕсли
ОсталосьСимволов = 0 Тогда
            Если (
Код = 43) и (не WindowsFileURI) Тогда
               
// Символ(43) = «+»
               
Код = 32; // Символ(32) = » » (пробел)
           
КонецЕсли;
           
Результат = Результат + Символ(Код);
           
Инд = Инд + 1;
            Продолжить;
        КонецЕсли;

        Если Код <= 127 Тогда
           
// Код = 0b0ххххххх
           
Результат = Результат + Символ(Код);
        ИначеЕсли
Код <= 191 Тогда
           
// Код = 0b10хххххх
           
ПолныйКод = (ПолныйКод*64) + (Код%64); // shl(ПолныйКод, 6) + (Код & 0x3F)
           
ОсталосьСимволов = ОсталосьСимволов 1;
            Если
ОсталосьСимволов = 0 Тогда
               
Результат = Результат + Символ(ПолныйКод);
            КонецЕсли;
        ИначеЕсли
Код <= 223 Тогда
           
// Код = 0b110ххххх
           
ПолныйКод = Код % 32; // Код & 0x1F
           
ОсталосьСимволов = 1;
        ИначеЕсли
Код <= 239 Тогда
           
// Код = 0b1110хххх
           
ПолныйКод = Код % 16; // Код & 0x0F
           
ОсталосьСимволов = 2;
        ИначеЕсли
Код <= 247 Тогда
           
// Код = 0b11110ххх
           
ПолныйКод = Код % 8; // Код & 0x07
           
ОсталосьСимволов = 3;
        ИначеЕсли
Код <= 251 Тогда
           
// Код = 0b111110хх
           
ПолныйКод = Код % 4; // Код & 0x03
           
ОсталосьСимволов = 4;
        ИначеЕсли
Код <= 253 Тогда
           
// Код = 0b1111110х
           
ПолныйКод = Код % 2; // Код & 0x01
           
ОсталосьСимволов = 5;
        КонецЕсли;

        Инд = Инд + 1;
    КонецЦикла;

    Возврат Результат;
КонецФункции

Примеры:

URL = ДекодироватьURL(«http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80»);
// URL = «http://ru.wikipedia.org/wiki/Пример»

URL = ДекодироватьURL(«c:documents%20and%20settings»);
// URL = «c:documents and settings»

Вот и все)

PS. Очень жаль, что 1С в платформе 8.х до сих пор не реализовала битовых операций. Поэтому реализация данной функции не столь изящна, как могла бы быть.

 

Updated 10.12.11: Исправлена ошибка при декодировании URI в протоколе file:// в Windows. Добавлен второй параметр в функции WindowsFileURI — признак того, что декодируется именно такая строка. При значении этого параметра Ложь — обработка как для «обычных» 🙂 интеренет протоколов.

14 Comments

  1. Yashazz

    А ещё есть такая штука, regexp называется.

    Reply
  2. Foxx

    (1) Yashazz, представьте себе, я в курсе)

    Но в данном случае она здесь не помощник.

    Reply
  3. Трактор

    Такая публикация уже есть http://infostart.ru/public/70330/

    Reply
  4. Foxx
    Трактор пишет:

    Такая публикация уже есть http://infostart.ru/public/70330/

    Не совсем так. Указанная публикация выполняет преобразование в обратную сторону :). Т.е. из «Микроскоп» в «%D0%9C%D0%B8%D0%BA%D1%80%D0%BE%D1%81%D0%BA%D0%BE%D0%BF».

    А у меня — из «%D0%9C%D0%B8%D0%BA%D1%80%D0%BE%D1%81%D0%BA%D0%BE%D0%BF» в «Микроскоп» 🙂

    Reply
  5. Maks_Payn

    Очень интересно и позновательно! Спасибо! ))

    Reply
  6. Murom

    Спасибо ,помогло.

    Как раз собрал для модуль для преобразования в код URL и обратно.

    Было бы удобно ,если б в статье была не только процедура декодирования ,но и преобразования в код URL.

    Reply
  7. Foxx

    (6) Murom, рад, что помогло))

    Про кодирование строки в обе стороны — такая задача в данной статье не ставилась, т.к. на инфостарте уже существуют публикации для обратного преобразования. См. например, ссылку в (3)

    Reply
  8. Windsor77

    (6) Murom, если интересно, вот мой вариант Текст->ULR (Unicode -> UTF-8).

    Reply
  9. Murom

    (8) Windsor77,

    Спасибо, посмотрю.

    А так уже сам написал и забыл.

    Где-то в парсере JSON крутиться. Пока без проблем.

    Reply
  10. graphbuh

    Интересно, почему это не работает для запросов яндекса. За пример плюс.

    Reply
  11. Foxx

    (10) а что не так с запросами яндекса? Можно пример?

    Reply
  12. graphbuh

    Пожалуйста, Тарас.

    допустим здесь я пишу поиск — «веселые картинки» в форме поиск яндекса

    http://www.proza.ru/search.html

    после этого открывается страница запроса с текстом

    http://www.proza.ru/cgi-bin/search.pl?text=%E2%E5%F1%E5%EB%FB%E5+%EA%E0%F0%F2%E8%ED%EA%E8&searchid­=126972&l10n=ru&web=0#1073

    т.е. кусок %E2%E5%F1%E5%EB%FB%E5+%EA%E0%F0%F2%E8%ED%EA%E8 это закодированная кириллица.

    получаю

    http://www.proza.ru/cgi-bin/search.pl?text=+&searchid=126972&l10n=ru&web=0#1073

    Reply
  13. Foxx

    (12) там они изобрели свой собственный способ кодирования).

    У них там строка закодирована в кодировке Windows-1251 (судя по внешнему виду, не проверял)

    А моя функция декодирует UTF-8

    «веселые картинки» по-правильному URL-кодированию будет

    %D0%B2%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%BA%D0%B0%D1­%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8

    Reply
  14. graphbuh

    Спасибо за информацию, Тарас. Вчера вечером прочитал, что начиная с некоторого момента они применяют шифрование (

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *