Posts

Showing posts from May, 2009

Интернационализация ns_sendmail

Понадобилось отправлять почту без вложений, а это как раз тот случай, когда вызов внешней утилиты оказывается слишком накладно. Потому сделал враппер для встроенной в AOL функции ns_sendmail, умеющий корректно обрабатывать не-ASCII символы. # note: _ns_sendmail is exists! if {[info commands orig_ns_sendmail] eq {}} { rename ns_sendmail orig_ns_sendmail package require base64 package require mime # headers are ignored! proc ns_sendmail {to from subject body args} { set headerSet [ns_set create] ns_set put $headerSet Content-Type {text/plain; charset=UTF-8} ns_set put $headerSet Content-Transfer-Encoding base64 ns_set put $headerSet MIME-Version 1.0 orig_ns_sendmail $to \ $from \ [mime::word_encode utf-8 quoted-printable [encoding convertto utf-8 $subject]] \ [base64::encode [encoding convertto utf-8 $body]] \ $headerSet [lindex $args

SQLite 3.6.14.2

Выпущено внеочередное обновление SQLite, то бишь версия 3.6.14.2. Обновление исправляет единственный баг, который приводит к выдаче неправильного результата запроса. Обнаружить этот баг сложно и нет способа на уровне приложения обойти, потому предлагается обновление. Баг-репорт и патч доступны здесь: http://www.sqlite.org/cvstrac/tktview?tn=3879 http://www.sqlite.org/cvstrac/chngview?cn=6677 Баг затрагивает только версии 3.6.14 и 3.6.14.1, для пользователей этих версий настоятельно рекомендуется обновиться. Ну а я в ближайшее время обновлю версию SQLite в своем репозитории.

Well-known text (WKT) и Tcl

Well-known text - стандартный формат предоставления геоинформации во многих системах, в том числе, с этим форматом умеют работать OGR, Spatialite, PostGIS. Неплохо бы с этим форматом уметь и напрямую работать, из тиклевой программы. А реализовать это можно вот так: 1. Преобразование во вложенные тиклевские списки: proc WKT_read {wkt} { return [string map {, " " \ ( " {" \ , " " \ ) "} " \ } $wkt] } WKT_read {POINT(6 10)} POINT {6 10} WKT_read {LINESTRING(3 4,10 50,20 25)} LINESTRING {3 4 10 50 20 25} WKT_read {POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2, 3 2, 3 3, 2 3,2 2))} POLYGON { {1 1 5 1 5 5 1 5 1 1} {2 2 3 2 3 3 2 3 2 2} } WKT_read {MULTIPOINT(3.5 5.6,4.8 10.5)} MULTIPOINT {3.5 5.6 4.8 10.5} WKT_read {MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))} MULTILINESTRING { {3 4 10 50 20 25} {-5 -8

GPS конверторы - второе пришествие

Как говорится, все новое - это хорошо забытое старое. Вот и я вспомнил про сделанные когда-то онлайн-конверторы форматов трэков с GPS. Побудил меня к этому ничто иное, как главный двигатель прогресса, то бишь лень. Ну не хочется мне каждый раз вручную набирать команду преобразования трэка, а потом полученный файл закачивать на веб-сервер, откуда его можно просмотреть с помощью Google Maps (понятно, что Google Earth может и локальный файл просмотреть, но ведь хочется и друзьям ссылочку отправить). Напоминаю адрес - https://mobigroup.ru/page/services . Впрочем, образовалась некая проблема - трэков становится все больше (у меня навигатор Garin Oregon 300, трэки умеет сохранять в формате Mapsource в файлах с расширением mps, - в России, к сожалению, он не очень известен, может быть, надо обзорчик написать? если вам интересно, пишите, сделаем обзор), и искать среди них нужный все сложнее. Посему появляется желание сделать онлайн-систему хранения и управления трэками. Думаю, нужны следующие

Релиз Spatialite 2.3

На самом деле, релиз вышел уже энное время назад, но только сегодня я добрался до него. Итак, занимаюсь валидацией исходников. Бета-версию Spatialite 2.3 мне присылал автор, я ее интегрировал в дерево исходников SQLite в виде набора модулей, в том числе поправил некоторые баги, в том числе переполнение int в модуле VirtualText, который я много где использую (а обнаружил ошибку, когда начал загружать с помощью этого модуля телефонные номера в биллинг - по стандарту номера бывают до 15-ти знаков, и вот тут-то и нарисовались аккуратно прикопанные грабли). Как оказалось, этот самый неприятный баг автор почему-то забыл поправить и я снова отправил ему сообщение об этом прискорбном факте (или даже инциденте, уж больно баг неприятный, сразу и не заметить, ведь проблема не в коде, а в логике). Итак, к настоящему моменту я проверил код VirtualText, VrtualShape, iconv (автор его по-другому называет, но для меня, черт побери, имя файла gg_utf8 и название функций с префиксом gaia* отнюдь не очеви

skylink-интернет с модемом ZTE MG478

0. Потребуются следующие файлы конфигурации: /etc/wvdial/skylink.conf [Dialer Defaults] Init2 = ATZ Init3 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 Stupid Mode = 1 Modem Type = Analog Modem ISDN = 0 Phone = #777 Modem = /dev/ttyUSB0 Username = "mobile" Dial Command = ATDT Password = "internet" Baud = 115200 /etc/wvdial/skylink-blocked.conf [Dialer Defaults] Init2 = ATZ Init3 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 Stupid Mode = 1 Modem Type = Analog Modem ISDN = 0 Phone = #777 Modem = /dev/ttyUSB0 Username = "mobile@blocked" Dial Command = ATDT Password = "internet" Baud = 115200 1. В ядрах до 2.6.26 включительно следует загрузить вручную модуль usbserial: sudo modprobe usbserial vendor=0x19d2 product=0xfffe 2. Если активен другой интерфейс, лучше отключить: sudo ifdown wlan0 3. А теперь можно и подключиться к skylink: а) при положительном балансе счета sudo wvdial -C /etc/wvdial/skylink.conf б) при отрицательном балан

Перекодирование видео для Ritmix RF-7400 с помощью mencoder

Когда-то давно довелось поразвлекаться, разбираясь, каким образом сконвертировать видео для плеера Ritmix RF-7400. "Штатного" перекодировщика в комплекте почему-то не было, на сайте производителя - тоже, пришлось искать на форумах и потом запускать под виндой на виртуалке. Оказалось, используется стандартный mencoder, для которого генерится bat-файл с параметрами запуска. Вот что получилось в итоге: mencoder -noodml "$1" -o "out_$1" -ofps 20.000 -vf-add scale=-2:128 -vf-add expand=176:128:::1 -ovc xvid -xvidencopts bitrate=384 -srate 44100 -oac mp3lame -lameopts vbr=0 -lameopts br=128 -lameopts vol=0 -lameopts mode=0 -lameopts aq=7 -lameopts padding=3 -af volnorm -xvidencopts max_bframes=0:nogmc:noqpel Здесь $1 - имя исходного файла, а результат будет сохранен в файл с добавлением префикса "out_". Все, можно загружать в папку video на устройстве и смотреть.

Заметка об XML, или "А Баба-Яга - против!"

Священная война вокруг xml поутихла и пришло время, когда можно здраво разобраться, что же нам этот самый xml принес. Многие приложения в эпоху бума перешли на использование xml, даже скорее не просто перешли, а перепрыгнули, поскольку процесс перехода был революционным. В отличие от априорных спекуляций мы рассмотрим, где же сегодня на практике используется xml и нужен ли он там. Можно выделить следующие широко распространенные области применения: Конфигурационные файлы Фактически, это замена юниксовым plain-text конфигурационным файлам и виндовым ini-файлам. Кроссплатформенный пример - VirtualBox. Можно придумать много резонов делать именно так, но на практике ясно одно - более неудобную реализацию еще поискать. Руками править плохо, делать скрипт для правки сложно (ага, есть некоторые утилиты, облегчающие жизнь, но с plain-text все намного проще). И самое плохое - разработчики, использующие xml для конфигов, для своего удобства и во избежание лишних затрат на парсинг xml дублируют и

Использование утилиты tidy для чистки html

Tidy утилита очень мощная и есть во многих дистрибутивах, вот только использовать ее из внешней программы немного не тривиально, т.к. утилита представляет собой потоковый обработчик. Когда-то мне пришлось поломать голову над тем, как же вызывать tidy корректно, а в итоге получилась нижеприведенная функция. proc tidy {buf} { if {$buf eq {}} {return {}} set res {} set cat [open "|cat" r+] set io [ open "|/usr/bin/tidy -utf8 -asxhtml -q --show-body-only 1 -f /dev/null <@ $cat" r] puts $cat $buf flush $cat close $cat set res [read $io] catch {close $io} return $res } Поскольку я работаю с дистрибутивом debian, то путь задан непосредственно в коде. Разумеется, точно так же можно вызывать из тикля любую другую утилиту потоковой обработки, например, архиватор.

HAProxy vs. Pound

Некоторое время назад столкнулся с неприятным "притормаживанием" при выполнении запросов. Как выяснилось, проблема в реверс-прокси Pound - в режиме HTTPS его эффективность оказалась не слишком высокой. Трафик проекта, на котором это произошло, составляет около 200 Gb в месяц, или миллион "с гаком" запросов в сутки (весь трафик по протоколу HTTPS). Притом в режиме HTTP (по отзывам разработчиков в рассылке AOLServer) Pound выдерживает до 800 запросов в секунду (ну, правда, неизвестно, на каком железе), после чего приходится ставить другой прокси. В качестве альтернативы выбрал HAProxy - и код понравился, и автор помог перенести конфиг Pound. Также оказалось очень полезным, что автор HAProxy написал патч к Stunnel4 для поддержки хидера X-forwarded-For (этот патч понадобилось немного адаптировать к версии stunnel4 в debian lenny, результат можно взять на сайте HAProxy или уже собранный пакет Stunnel4 в моем репозитории). Что приятно, после замены реверс-прокси в top-е е

Багфикс ns_httptime в AOLServer

Началось все с того, что обнаружил неприятную вещь - AOLServer 4.5.1 для файлов, созданных с 1-го по 10-е число любого месяца, никогда не отдает код ответа 304, а всегда заново их пересылает. Т.е. не работает кэширование, т.к. браузер сообщает, что актуальный файл в кэше есть, но сервер "не понимает". Обнаружил я эти "грабли" в процессе написания своей системы кэширования, которая еще и gzip-сжатие определенных типов файлов выполняет. Т.к. мне нужна работа в non-english локали, то я использовал debian-овский патч для ns_httptime, убирающий локалезависимость этой функции, а в нем и оказалась ошибка. Исправленный патч можно взять здесь: http://mobigroup.ru/files/aol4.5.1/httptime.c.diff --- httptime.c.orig 2003-01-18 22:24:20.000000000 +0300 +++ httptime.c 2009-05-12 20:14:24.000000000 +0400 @@ -27,6 +27,9 @@ * version of this file under either the License or the GPL. */ +static char *weekdays_names[7] = +{ "Sun", "Mon", "Tue", "

Tcl и JSON

Все чаще использую формат JSON, но средства его генерации в тикле... как бы это сказать... ужасают. В tcllib и вовсе неработающий код (да, deb-пакет tcllib пересобрал, заодно обновив версию, ибо безобразие это надо лечить). Пересмотрел множество реализаций, и что же - все авторы спотыкаются на несоответствии типов данных. Как пример: set json [::json::encode [list object [list code [list string $code] msg [list string $msg] id [list number $id]]]] Одним словом, интуитивно понятным такой код не назовешь. Самое интересное, что JSON - нетипизированный формат. А раз нетипизированный, то нет никакой необходимости указывать эти самые типы, как это делается во многих реализациях. Значит, можно сделать следующим образом - тиклевскому array (в виде списка, разумеется) ставим в соответствие JSON object, а тиклевскому list - JSON array. В Tcl array будем рассматривать ключи как строки (и, если нужно, эскейпить и заключать в дойные кавычки). Отсюда получаем следующую реализацию: # keys are not esc