понедельник, 22 марта 2010 г.
Puri и utf-8
Всё началось с того, что я обнаружил, что restas-directory-publisher не может обрабатывать URL, содержащие #\+. Исследование показало, что используемая функция hunchentoot:url-decode, по совершенно неведомой мне причине, заменяет #\+ на #\Space (так нужно делать при декодировании форм, но не url). Чуть присмотревшись к коду функций hunchentoot:url-decode и hunchentoot:url-encode я вообще перестал понимать, что именно они делают и какому rfc это соответствуют, но, в большинстве случаев, результат приемлем. При этом, hunchentoot:url-decode вообще не очень хорошо реализована и я сначала попробовал переписать её как-нибудь более вменяемо. После чего вдруг вообще мои приложения отказались обрабатывать url, содержащие кириллицу. Что меня ввело в ступор, поскольку я был уверен в своём коде. Начав копать дальше вдруг обнаружил, что замечательная библиотека Puri жутко коверкает подобные url, ибо просто игнорирует тот факт, что для кодирования символов используется кодировка utf-8. Примечательным моментом при этом было то, что совместное использование Puri и hunchentoot:url-decode давало обычно приемлемый результат. А поскольку я обычно использовал их в связке, то долго не обращал внимания на эту проблему. Ну и тот факт, что всё работало, вселял в меня уверенность, что этим библиотекам можно доверять. Как оказалось, это классический случай, когда минус на минус давал плюс и приемлемые результаты получались только из-за довольно топорного и прямого метода реализации hunchentoot:url-decode: стоило переписать эту функции в чуть более интлектуальном виде, так сразу полезли проблемы. Итого, функциям hunchentoot:url-decode и hunchentoot:url-encode вообще нельзя доверять, а Puri содержит в себе серьёзную проблему. Самая большая моя проблема в том, что Puri лежит в основе используемого мною подхода, а более детальный анализ показал, что возможность декодирования url за пределами Puri вызывает весьма серьёзные проблемы (в случае работы с нетривиальными url). Мемного поразмыслив решил, что иного пути, как патчить Puri просто нет. В общем, это замечательная библиотека, вот только о существовании utf-8 не подозревает. Исправить код оказалось не очень сложно, патчи отослал разработчику. Но как-то многовато патчей я отослал за последние полторы недели и толи английский мой совсем плох, то со мной что не так, но только отвечать мне не спешат. Да и по прошлому опыту помню, что на некоторые патчи бывает приходит ответ спустя несколько недель. Так что пока решил разместить форк Puri с моими исправлениями на github.
Подписаться на:
Комментарии к сообщению (Atom)
Наличие индусокода в лисповых проектах не может не печалить
ОтветитьУдалитьА вы много в своих проектах закладываетесь, например, на то, что буквы могут быть иероглифами, печатаемые справа налево, снизу вверх? ;)
ОтветитьУдалитьНу или когда на C/C++ пишите, много ли вы обращаете внимания на невыровненный доступ, LSB/MSB, etc?
7-битные американцы - проблема не американцев.
а причем тут индусокод?
ОтветитьУдалитьПросто малое комьюнити, что влечет соответствующие проблемы. Не мейнстрим, так сказать. Или нужно пользоваться коммерческими реализациями. К сожалению, вот так:(
@13-49
ОтветитьУдалитьПравильно, проблема не в конкретной библиотеке, а в малом количестве пользователей, малом количестве багрепортов и мало количестве патчей, ну и имеющей место безответственности. CL, как я недавно уже говорил, это не меч-кладенец, и нельзя надеяться, что один человек разработает очень качественное решение (такое бывает, но редко). По моим наблюдениям, самый качественный код (именно код) в SLIME, просто потому, что это самый востребованный проект на CL, но у него другие проблемы (о коих я писал раньше)...
По факту, в мире CL ты должен быть готов много пилить, по крайней мере на данном этапе.
> Или нужно пользоваться коммерческими
ОтветитьУдалить> реализациями.
Наивный, если говорить о Puri, то это портабельная версия http://github.com/franzinc/uri, которая отрыта, но написана коммерческим поставщиком, я специально посмотрел, там те же самые проблемы.
Это вообще большой миф, что коммерческие решения обладают более высоким качеством. Это верно для некоторых конкретных решений, но не распространяется автоматически на всё.
>Это вообще большой миф, что коммерческие решения обладают более высоким качеством.
ОтветитьУдалитьДа я с этим и не спорю. коммерческий софт != качественный софт. Те же GNU emacs, XEmacs или eclipse - примеры хороших открытых программ. Или slime. Но в мире CL, возможно, на данный момент лучше пользоваться коммерческими реализациями (если возможно по деньгам). Я, конечно, за развитие открытых библиотек и реализаций CL, но пока низкая популярность и комьюнити. Может быть со временем допилится.
Я тоже не люблю коммерческий софт в софтостроении, поскольку он, как правило, не дает гибкости в управлении кодом и т.д.
А замена #\+ на #\Space не на уровне reader идет?
ОтветитьУдалить> А замена #\+ на #\Space не на уровне reader идет?
ОтветитьУдалитьНет, конечно, это же просто строки, в hunchentoot:url-decode есть такой код:
(case char
((#\+) #\Space)
(otherwise char))
Что-то не совсем корректно он юникод сейчас понимает (ставил версию из твоего оверлея gentoo-lisp):
ОтветитьУдалить(puri::decode-escaped-encoding "/%D0%98%20" "")
"/И%98"
А должно быть "/И "
Из restas-а он как-то по-другому вызывается, там это приводит к сигнализированию ошибки babel-ем (при попытке декодировать %98 как utf8)
> (puri::decode-escaped-encoding "/%D0%98%20" "")
ОтветитьУдалитьПросто неправильный вызов, decode-escaped-encoding имеет следующие параметры (string escape reserved-chars), где escape означает надо ли декодировать, а reserved-chars это символы, которые не надо декодировать, при чём, в формате битового массива. Попробуй (puri::decode-escaped-encoding "/%D0%98%20" t nil)
> Из restas-а он как-то по-другому вызывается
Хм, где? Я изменил puri в оверлее и вскрыл этим массу проблем, ибо я часто раньше использовал hunchentoot:url-decode для url, полученных с помощью puri, что как я теперь понял является полной глупостью. Сейчас я изменил genurl в restas, который теперь использует puri для корректной генерации url, но эта версия пока только в git. Также надо разбираться отдельно и с другими моими пакетами, особенно большие проблемы с restas-wiki. Мне потребуется некоторые время, что бы всё это разгрести.
Но зато мне теперь открылся "истинный путь" для работы с url :)