понедельник, 11 февраля 2008 г.

Разбитый PocketPC

На прошлой неделе разбил свой КПК Toshiba e330. Подаренный в своё время ssh-ом, он мне прослужил больше года. Однако оказалось, что удара кулака в морду он не выдерживает. :-(

КПК использовался только для чтения. Видимо, из-за моральной и физической старости, на нем сильно глючил сенсорный экран и кнопки на крестовине. Собственно за что он и получил удар в порыве злости. На экране ещё с пол часа светилось последнее в его жизни изображение — страница из книги Виктора Астафьева «Прокляты и убиты. Часть вторая». Теперь мне нужен новый КПК, ведь очень хочется узнать чем все там закончилось...

среда, 30 января 2008 г.

Веб-программирование на perl и шаблоны html страниц

Как я уже не раз замечал, обычно всякий веб-программист на perl проходит в своём развитии следующие стадии:

  1. Шаблоны станиц не используются. Характерно для начинающих, совсем зеленых ещё программистов. Вывод страниц формируется непосредственно внутри скрипта, примерно следующим образом:

    my $title = 'Hello world';
    print "Content-type: text/html\n\n";
    print "<html><head><title>$title</title></head>";

    Проект начинает расти и программист замечает, что становится неудобно вносить изменения в дизайн страницы. Редактирование исходного кода программы нелогично, ведь алгоритм работы остается неизменным! Работа с html тегами осложнена, они же встаиваются в синтаксис другого языка, появляется избыточный синтаксический мусор. Про разделение труда на программиста и верстальщика и вообще говорить нечего, здесь оно невозможно. Так программист приходит к следующей стадии.

  2. Самописная шаблонная система. Теперь вывод страниц формируется при помощи отдельной функции. Шаблон загружается из внешнего файла. С помощью регулярных выражений в нем организуется поиск и замена фрагментов кода, например специально помеченных комментариев:

    <table>
        <tr>
            <td><img src="logo.gif"></td>
            <td><!-- $TopMenu --></td>
        </tr>
        <tr>
            <td><!-- $LeftMenu --></td>
            <td><!-- $Content --></td>
        </tr>
    </table>

    Иногда реализуется функциональность вставки других файлов в шаблон (Include). По сравнению с начальным вариантом — это большой шаг вперед, программист освобождается от большинства описанных недостатков. Это уже не «ходьба пешком», но ещё и не «езда на лимузине». Обычно собственная шаблонная система работает неоптимально и не предоставляет многих возможностей разработчику. Многие программисты надолго, если не на всегда, застревают на данной стадии и необоснованно гордятся своими поделиями. Другие же обрашаются к:

  3. Одна из общепризнанных шаблонных систем. От самописной системы они отличаются возможностями:

    • Полное разделение логики программы и внешнего вида страницы. Весь html код находится в шаблоне, скрипт сам не выдает ни одного тега.
    • Условные вставки. Фрагмент шаблона появлется на странице при выполнении какого-либо условия.
    • Обработка циклов или массивов переменных. Например, к элементам массива может быть применена одинаковая разметка и сформирована html таблица.
    • Дополнительные возможности — кеширование шаблонов и/или сгенерированных страниц, подключение пользовательских плугинов/фильтров.
    • Годы поддержки и развития, хорошее быстродействие.

    В мире perl наиболее известными шаблонными системами являются:

Выбор конкретной системы — вопрос личных вкусов и предпочтений, я использую HTML::Template. Она мне нравится за простой язык шаблонов, напоминающий html теги, без попыток создать новый язык программирования. Но подробный рассказ о этой шаблонной системе — тема для отдельной статьи. В завершение хочу заметить что применять шаблоны можно не только для создания html страниц. На CPAN присутствуют модули для создания excel и pdf документов из xml шаблонов. Пример создания excel таблицы на perl из xml шаблона мною был уже описан.

вторник, 11 декабря 2007 г.

Активация windows и http прокси

Решение проблемы активации операционных систем семейства windows при использовании http прокси сервера squid, требующего авторизации пользователей.

Я никогда не работал с лицензионной ОС windows. Раньше была ворованная, теперь уже 2 года как я не использую windows совсем, ни дома, ни на работе. Но возникла задача: в организации не могут активировать свой легально купленный экземпляр windows через интернет. Доступ к интернет осуществляется через http прокси сервер squid, требующий авторизацию пользователей.

Гугление дает описание этой ошибки в базе данных глюков, которую сама микрософт почему-то называет «базой знаний». Предлагается на выбор 3 варианта костылей:

  1. Отказаться от авторизации пользователей на http-прокси сервере.
  2. Задать список урлов, не требующих авторизации:

    • http://go.microsoft.com/*
    • https://sls.microsoft.com/*
    • https://sls.microsoft.com:443
    • http://crl.microsoft.com/pki/crl/products/MicrosoftRootAuthority.crl
    • http://crl.microsoft.com/pki/crl/products/MicrosoftProductSecureCommunications.crl
    • http://www.microsoft.com/pki/crl/products/MicrosoftProductSecureCommunications.crl
    • http://crl.microsoft.com/pki/crl/products/MicrosoftProductSecureServer.crl
    • http://www.microsoft.com/pki/crl/products/MicrosoftProductSecureServer.crl
  3. Активировать копию windows по телефону.

Для решения проблемы используем костыль №2. Добавляем следующие строки в файл конфигурации squid — /etc/squid/squid.conf

acl micro_act dstdom_regex microsoft\.com$
http_access allow micro_act

После перезапуска squid разрешит обращаться к сайтам, имя которых оканчивается на microsoft.com, не требуя авторизации. Это позволит провести активацию windows, правда учета трафика на эти сайты уже не будет. Это зло, с которым придется смириться. Вот уж не предполагал, что использование легального программного обеспечения создает дополнительные трудности пользователям.

понедельник, 5 ноября 2007 г.

Сравнение производительности perl кода

Иногда требуется выяснить как быстро работает тот или иной фрагмент кода на perl. Для этого можно использовать perl модуль Benchmark, входящий в стандартную поставку perl.

Задача. Как оптимальнее организовать перебор элементов хеша, например просуммировать значения всех ключей. В полном соответствии с принципом TIMTOWTDI существует несколько вариантов решения задачи:

Вариант №1. Использование цикла «foreach ( values ... )».

sub hash_values_sum_1(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ foreach values %hash;
    return $sum;
}

Вариант №2. Использование конструкции«map ... values ... ».

sub hash_values_sum_2(%) {
    my %hash = @_;
    my $sum = 0;
    map { $sum += $_ } values %hash;
    return $sum;
}

Вариант №3. Использование цикла «while ( ... each ... )».

sub hash_values_sum_3(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ while (undef, $_) = each %hash;
    return $sum;
}

Для проверки проверки напишем небольшой тестовый скрипт:

#!/usr/bin/perl -w
use strict;
use Benchmark qw/ :all /;

my %hash = map { rand, rand } ( 1 .. 1000 );

cmpthese( 5_000_000 , {
    var1 => 'my $sum = 0; $sum += $_ foreach values %hash',
    var2 => 'my $sum = 0; map { $sum += $_ } values %hash;',
    var3 => 'my $sum = 0; $sum += $_ while (undef, $_) = each %hash;',
} );

Проверяем производительность трех вариантов решения задачи. Для этого используем тестовый хеш, содержащий 1000 случайных ключей со случайными значениями. Для получения усредненных результатов, каждый из вариантов запускается по 5 миллионов раз. Результаты работы скрипта:

          Rate variant_1 variant_3 variant_2
var1  946970/s        --      -48%      -73%
var3 1838235/s       94%        --      -48%
var2 3546099/s      274%       93%        --

По таблице результатов видно, что:

  1. Вариант №3 работает почти в 2 раза быстрее, чем вариант №1.
  2. Вариант №2 работает почти в 2 раза быстрее, чем вариант №3.

В данном конкретном случае вариант №2 является однозначным победителем. Его использование более предпочтительно.

пятница, 19 октября 2007 г.

Пересборка пакетов Slackware

Иногда приходится пересобирать стандартные пакеты Slackware. Зачем? Причины могут быть разные, но чаще всего из-за того, что в стандартной сборке не указаны необходимые опции компиляции.

Пример 1. Вплоть до Slackware 12 так были вынуждены делать все, кому требовался интерпретатор языка perl с поддержкой многопоточности.
Пример 2. Не так давно я радовался, что в Slackware 12 включен пакет для создания шифрованных туннелей openvpn. К сожалению, когда дело дошло до практики мне он оказался совершенно бесполезен без возможности чтения пароля из файла. Опция конфигурации «auth-user-pass /path/to/file» и отвечает за это параметр компиляции «--enable-password-safe».

Сборка пакетов в Slackware осуществляется с помощью так называемых SlackBuild скриптов. SlackBuild скрипт — это обычный shell-скрипт, который осуществляет распаковку архива исходного кода программы, возможно наложение патчей, конфигурирование, компиляцию и запаковку в пакет Slackware. Все SlackBuild скрипты для стандартных пакетов Slackware открыты для свободного доступа и могут быть получены по адресу ftp://ftp.slackware.com/pub/slackware/slackware-<version>/source/, где <version> — это требуемая версия Slackware, одно из «8.1», «9.0», «9.1», «10.0», «10.1», «10.2», «11.0» или «12.0».

Рассмотрим подробнее процесс пересборки стандартного пакета Slackware на примере пакета openvpn. Сначала выкачиваем всё необходимое для сборки:

root@darkstar:~# mkdir /usr/src/openvpn; cd /usr/src/openvpn
root@darkstar:/usr/src/openvpn# wget --recursive --no-directories \
> ftp://ftp.slackware.com/pub/slackware/slackware-12.0/source/n/openvpn
...

root@darkstar:/usr/src/openvpn# ls -la
total 681
drwxr-xr-x 2 root root    264 2007-10-19 08:32 ./
drwxr-xr-x 6 root root    184 2007-10-19 08:30 ../
-rw-r--r-- 1 root root   1375 2007-06-10 01:25 README
-rw-r--r-- 1 root root 669076 2006-10-01 00:00 openvpn-2.0.9.tar.gz
-rw-r--r-- 1 root root    189 2006-10-01 00:00 openvpn-2.0.9.tar.gz.asc
-rw-r--r-- 1 root root   3729 2007-06-12 04:09 openvpn.SlackBuild
-rw-r--r-- 1 root root   6942 2007-06-12 03:48 openvpn.conf.sample
-rw-r--r-- 1 root root    888 2007-06-10 01:23 slack-desc

Прежде всего здесь нас интересует файл openvpn.SlackBuild. Применим следующий патч:

@@ -23,8 +23,8 @@
 VERSION=2.0.9
 ARCH=${ARCH:-i486}
 BUILD=${BUILD:-1}
-#TAG=${TAG:-_SBo}
-unset TAG
+TAG=${TAG:-_SBo}
+# unset TAG
 CWD=`pwd`
 TMP=${TMP:-/tmp}
 PKG=$TMP/pkg-$PRGNAM
@@ -60,6 +60,7 @@
   --sysconfdir=/etc/openvpn \
   --localstatedir=/var \
   --enable-lzo \
+  --enable-password-safe \
   --build=$ARCH-slackware-linux
 
 make || exit 1

Внесенные изменения:

  1. Включена поддержка поля TAG в наименовании пакета. TAG — это идентификатор создателя пакета, добавляется в самом конце имени файла, после номера сборки. В стандартных пакетах отсутствует, а в дополнительно устанавливаемых крайне желателен.
  2. Добавлена опция конфигурирования «--enable-password-safe», то, собственно ради чего вся пересборка и затевается.

Запускаем процесс пересборки пакета:

root@darkstar:/usr/src/openvpn# chmod +x openvpn.SlackBuild
root@darkstar:/usr/src/openvpn# TAG=nmu OUTPUT=`pwd` ./openvpn.SlackBuild
...

root@darkstar:/usr/src/openvpn# ls -la *.tgz
-rw-r--r-- 1 root root 316375 2007-10-18 17:39 openvpn-2.0.9-i486-1nmu.tgz

Если все прошло без ошибок в текущей директории получим файл openvpn-2.0.9-i486-1nmu.tgz. Обновить уже установленный пакет можно с помощью команды:

root@darkstar:/usr/src/openvpn# upgradepkg openvpn-2.0.9-i486-1nmu.tgz

+==============================================================================
| Upgrading openvpn-2.0.9-i486-1 package using ./openvpn-2.0.9-i486-1nmu.tgz
+==============================================================================

Pre-installing package openvpn-2.0.9-i486-1nmu...

Removing package /var/log/packages/openvpn-2.0.9-i486-1-upgraded-2007-10-18,17:44:08...

Installing package openvpn-2.0.9-i486-1nmu... 
PACKAGE DESCRIPTION:
openvpn: openvpn (secure IP tunnel daemon)
openvpn:
openvpn: OpenVPN is a full-featured SSL VPN which can accomodate a wide range
openvpn: of configurations, including remote access, site-to-site VPNs, WiFi
openvpn: security, and enterprise-scale remote access with load balancing,
openvpn: failover, and fine-grained access-controls.
openvpn:
openvpn: OpenVPN's home on the net is:  http://openvpn.net
openvpn:
Executing install script for openvpn-2.0.9-i486-1nmu...

Package openvpn-2.0.9-i486-1 upgraded with new package ./openvpn-2.0.9-i486-1nmu.tgz.

Все, стандартный пакет Slackware пересобран с необходимыми нам опциями и успешно установлен в системе. Вообще изучение стандартных SlackBuild скриптов это хорошая отправная точка для написания собственных. В конце пара ссылок:

http://www.linuxpackages.net/howto.php
Документация по сборке пакетов для Slackware.
http://www.slackbuilds.org
Репозитарий SlackBuild скриптов для многих программ, официально не входящих в дистрибутив.

четверг, 20 сентября 2007 г.

Поиск в Google Maps

Врядли кто-то из жителей Комсомольска-на-Амуре знает где находится улица Путейская. Конечно кроме непосредственно живущих на ней :-). Когда мне там что-то понадобилось, блиц-опрос окружающих ничего не дал. Как ни странно, в итоге мне помог интернет, а конкретно поиск на сервисе Google Maps. Достаточно было в поисковую строку ввести фразу «Комсомольск-на-Амуре, ул. Путейская» и сразу получил карту города отцентрованную на искомой улице. А также возможнось встроить фрагмент карты в веб-страничку, чем здесь и воспользовался:


Просмотреть увеличенную карту

А улица Путейская оказалась в той ещё жопе, не удивительно что раньше я про неё не слышал.

понедельник, 3 сентября 2007 г.

Catalyst, HTTP авторизация и FastCGI

Описанный ранее способ использования http-авторизации в Catalyst проектах упорно не хотел работать с FastCGI протоколом. Использовалось:

  1. Веб-сервер apache версии 2.2.x.
  2. Модуль подержки протокола FactCGI для веб-сервера apache — mod_fascgi версии 2.4.2. Кстати, mod_fastcgi для apache 2.2 без небольшого патча не собирается. Смотри здесь.
  3. Движок Catalyst для обработки запросов по протоколу FastCGI — Catalyst::Engine::FastCGI.

В итоге оказалось две причины:

  1. По протоколу CGI http-заголовок Authorization должен передаваться внешнему приложению в качестве одноименной переменной окружения. Почему-то модуль mod_fastcgi по-умолчанию этого не делает, однако предусматривает специальную опцию -pass-header при передаче запроса FastCGI обработчику. Пример использования в файле конфигурации apache — httpd.conf:

    FastCgiServer                           \
        /root/MyApp/script/myapp_fastcgi.pl \
        -pass-header Authorization
  2. После этого стала доступна переменная окружения Authorization, однако плугин Authentication::Credential::HTTP всё ещё не работал! Дальше пришлось залезть в исходники библиотек Catalyst. Ошибка обнаружилась не в движке Catalyst::Engine::FastCGI, а в его базовом классе Catalyst::Engine::CGI. Из чего с увереностью можно сказать, что и движок Catalyst::Engine::CGI некорректно работает с http-авторизацией. После внесения следующих исправлений всё встало на свои места:

    @@ -95,7 +95,7 @@
     
         # Read headers from %ENV
         while ( my ( $header, $value ) = each %ENV ) {
    -        next unless $header =~ /^(?:HTTP|CONTENT|COOKIE)/i;
    +        next unless $header =~ /^(?:HTTP|CONTENT|COOKIE|Authorization)/i;
             ( my $field = $header ) =~ s/^HTTPS?_//;
             $c->req->headers->header( $field => $value );
         }

На моё сообщение в список рассылки Catalyst не последовало никакой реакции и ошибка сохраняется до сих пор — версия Catalyst::Runtime 5.7010 на текущий момент.