barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)
Показаны сообщения с ярлыком barbitoff_at_github. Показать все сообщения
Показаны сообщения с ярлыком barbitoff_at_github. Показать все сообщения

пятница, 13 апреля 2012 г.

Скробблинг на last.fm с MTP-девайсов в Linux

Скробблить всё, что слушаешь, на ласт - достаточно навязчивая привычка. Т.к. львиную долю музыки я слушал на плеере (сейчас правда перешел на андроидофон), возникло желание как-то вытягивать с него проигранные треки и скробблить на ласт. Встал  вопрос - каким же образом?
Плеер мой - старичок Creative Zen V, никакой операционки в нём и в помине нет, поэтому написанием приложения под неё не отделаться. Писать свою прошивку тоже желания не было =) Надежду во мне посеял тот факт, что плеер сохраняет для каждого трека число его проигрываний, которое можно посмотреть, зайдя в свойства трека в интерфейсе плеера. Осталось теперь научиться получать это число с ПК, и желательно, уметь ещё и обнулять его после скробблинга. Потеря времени проигрывания терка для меня лично была некритична - я готов был скробблить все загруженные с девайса треки "пачкой", начиная с некоторого заданного момента времени.
Т.к. ПК видит мой плеер как MTP-устройство, я сразу решил посмотреть, можно ли по MTP видеть число воспроизведений. Оказалось можно - это умеет даже проигрыватель Amarok. Раз умеет амарок - значит научусь и я, даже если придется покопаться в сорцах амарока. Копаться правда не пришлось - то ли в зависимостях, то ли где-то ещё, я увидел, что для работы с MTP-устаройствами он использует библиотеку libmtp, обладающую, как оказалось, отличной документацией с достаточным количеством примеров.  Так что встала задача разработки приложения, извлекающего проигрывания в некоторую БД, из которой потом уже можно сробблить. 
В итоге получилась консольная программка, извлекающая все треки с девайса и сохраняющая их в БД sqlite, после чего сбрасывающая счетчики проигрываний в плеере. По каким-то причинам, правда, я позже решил отказаться от sqlite, и стал вместо вставки данных в БД формировать SQL-дамп, который можно потом загрузить куда угодно (точнее в ту СУБД, которая съест используемый синтаксис).
Теперь дело встало за малым - извлечь инфу из БД, и заскробблить на ласт. Тут я решил поискать опенсорсный скробблер, т.к. копать REST-API ласта не хотелось. Вариант нашелся, имя ему - lastfmsubmitd, его можно поставить из репов Debian / Ubuntu. В его комплект, помимо демона-скробблера, входит вспомогательный скрипт-скробблер, принимающий параметры скроблимого трека через аргументы командной строки. Задача формирования последовательности вызовов этого скробблера (в виде sh-скрипта) на основании инфы из базы легла на php-скрипт, который написался достаточно быстро. 
В итоге последовательность действий для сробблинга получилась такая:
1) Подключаю девайс, запускаю свою C++-программку, формирую SQL дамп
2) Гружу дамп в MySQL
3) Правлю в php-скрипте время начала скробблинга, запускаю его, получаю на выходе sh-скрипт.
4) Запускаю sh, после того, как он отработает, запускаю демон скробблера lastfmsubmitd. И вуаля - треки улетают на ласт.
Сложновато конечно вышло =) Но работает, и с учетом того, что повторял я эти действия не очень часто - пару раз в неделю, меня это не особо напрягало. Ну а потом я разжился андридофоном (вернее, купил уже 4ый по счету андроидофон, на котором качество проигрывания музыки меня наконец-то устроило), и необходимость скробблить с плеера отпала - сробблеров под андроид полным полно.
Сорцы своих "творений" я выложил на github - вдруг кому будет интересно: https://github.com/barbitoff/mtpScrobblingUtils.

вторник, 10 апреля 2012 г.

Java: Валидация цепочки сертификатов с использованием расширения CRL Distribution Point с возможностью кэширования CRL

Java PKI API, а точнее, его реализация под названием PKIX, не имеет функционала по работе с расширением CRL Distribution Point (далее - CRL DP). Возможность проверки сертификатов по CRL есть, включается она следующим кодом:
builderParams.setRevocationEnabled(true);
, где builderParams - объект параметров построителя цепочки сертификатов PKIXBuilderParameters. Однако CertPathBuilder (или CertPathValidator) извлекают при этом эти самые CRL не по URL`у, указанному в CRL DP сертификата, а из т.н. CertStore.
Работа с CRL DP осуществляется уже на уровне реализации PKIX. Например, для Sun-овской реализации использование CRL DP при получении CRL включается следующим образом:
System.setProperty("com.sun.security.enableCRLDP", "true");    
Для реализации IBM устанавливаемое свойство имеет другое имя. 
Не знаю как в реализации от IBM, но в таковой от Sun я не нашел возможности как-либо управлять кэшированием CRL. Без кэширования использование проверки цепочки сертификатов в высоконагруженном веб-приложении практически невозможно: каждый запрос к приложению приводит к запросу CRL с Distribution Point (а если в цепочке сертификатов между проверяемым сертификатом и доверенным несколько сертификатов - то к нескольким CRL), что крайне негативно сказывается на производительности. Более того, каждый раз загружать CRL попросту не нужно (уж по крайней мере по несколько раз в минуту - точно).
Для решения этой проблемы можно воспользоваться открытой библиотекой jTrust: http://code.google.com/p/jtrust/. У неё тоже есть несколько минусов: во-первых, она жестко завязана на криптопровайдер Bouncy Castle, что особенно неудобно, когда в приложении уже используется другой криптопровайдер. Во-вторых, спроектирована библиотека таким образом, что предполагается её использование в качестве полной замены стандартному Java PKI API, а не как дополнение к нему, поэтому просто взять оттуда функционал по кэшированию CRL не получится. К тому же, реализация кэширования в ней имхо не вполне адекватная: для хранения CRL в кэше в памяти используются SoftReference, что приводит к очистке кэша сборщиком мусора, что, как минимум, не является ожидаемым поведением для кэша. В дополнение к этому, время жизни кэша отсчитывается почему-то не от момента загрузки CRL, а от момента времени, указанного в thisUpdate в самом CRL. Да ещё и устанавливать время жизни кэша можно только в часах. 
Подумав надо всем этим, я написал свою реализацию кэширующего репозитория для jTrust, код чуть позже выложу на github. А интегрировал в свое приложение библиотеку jTrust я следующим образом: строится и валидируется цепочка сертификатов средствами PKIX, а, точнее, его sun`овской реализации (неявно, т.к. эта реализация, как я понял, используется томкатом). При этом флаг revocationEnabled установлен в false, чтобы выполнялись все проверки, за исключением CRL. После успешного построения и валидации цепочки она дополняется trusted-сертификатом в конце (т.к. PKIX формирует цепочку, завершающуюся сертификатом, выданным доверенным субъектом, а jTrust оперирует цепочками, оканчивающимися непосредственно сертификатом самого доверенного субъекта), и используется CrlTrustLinker для проверки валидности каждой связи в цепочке (а в качестве репозитория CRL этот линкер использует мою самописную имплементацию интерфейса CrlRepository).

четверг, 22 марта 2012 г.

gRaphaël piechart: баг, связанный с игнорированием настройки "colors" при наличии единственного сектора

Ещё один баг gRaphaël piechart: если чарт содержит только один сектор, занимающий все 360 градусов, то библиотека игнорирует настройку colors, делая круг синего цвета. Покопавшись в исходниках (g.pie-min.js) я дейтсвительно нашел, что заливка устаналивается в 2 разных местах (видимо, для случая цельного круга и нескольких секторов). И если в случае с несколькими секторами используется выражение:
o.colors&&o.colors[y]||c.colors[y]||"#666"
, которое пытается найти цвет в конфигурации, а затем - в цветах по-умолчанию, то для цельного круга видим:
fill:c.colors[0]
, т.е. сразу берется цвет по-умолчанию. Исправление этого фрагмента на:
fill:o.colors&&o.colors[0]||c.colors[0]
решает проблему.
UP: посмотрел github проекта, соответствующее issue висит уже 2 года:  https://github.com/DmitryBaranovskiy/g.raphael/issues/24. 
Исправленная мной версия кода тут: https://raw.github.com/barbitoff/g.raphael/master/g.pie.js (не минимизированный файл) и тут: https://raw.github.com/barbitoff/g.raphael/master/min/g.pie-min.js (минимизированный).