You are viewing [info]nisoi's journal

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

UPD: нашлось! «Адажио» Гарри Бардина.

Бумажная анимация в чёрно-белых тонах. Идут по плоскости птице-люди чёрного цвета. И тут в их стройных рядах обнаруживается абсолютно белый экземпляр. Чёрные пытаются его запачкать, пятна пропадают. Мистика. Со злости чёрные растерзывают невезучего собрата на куски. Но тот собирается и взмывает вверх белоснежным нетронутым листом бумаги.

После восхождения Белого чёрная толпа начинает ему поклоняться, рисует плакаты с его ликом, всячески пропагандирует Белый след в тёмном народе, который обязательно пройдёт через унылую жизнь под очи Всевышнего и тоже осветлится.

И тут в их рядах появляется экземпляр серого цвета. Драматический финал.

И музыка такая известно-грустная.

Может, кто-нибудь видел?
 
 
11 December 2008 @ 10:25 pm
В httpd.h есть описание структуры server_rec — для хранения информации о каждом виртуальном хосте. И там все поля структуры вроде как прокомментированы. Это, мол, имя сервера, а это, значит, уровень логгинга, ну и так далее.

И вот там есть такой кусочек:


    /** MIME type info, etc., before we start checking per-directory info */
    struct ap_conf_vector_t *lookup_defaults;

    /* Transaction handling */

    /** I haven't got a clue */
    server_addr_rec *addrs;
    /** Timeout, as an apr interval, before we give up */
    apr_interval_time_t timeout;


Простите, а что значит «I haven't got a clue» в комментарии к addrs? Это переводится как «Не имею ни малейшего понятия» или мой девелоперский английский недостаточно хорош?

И это фактически основной заголовочный файл Apache. Что же дальше будет? I am afraid, Dave...
 
 
Очередное буйство байтов в IE 6.

Оказывается, если на страничке подключён какой-нибудь js-скипт (допустим, prototype), и путь до скрипта локальный, но вместо файла отдаётся 301 редирект на внешний prototype (допустим, на Google AJAX Libraries API), то IE 6 его не грузит.

В 7-м, кстати, всё нормально работает.

В общем, как обычно — зараза этот ваш шестой эксплорер.

С другой стороны — не стоит вообще такими извращениями заниматься.
 
 
Бывает так: есть flash-баннер, который должен ссылаться на какую-то странцу сайта. А адрес этой страницы неизвестен и станет известен только тогда, когда баннер собственно будет внедряться в код сайта. Или нужно иметь возможность менять ссылку во flash-баннере время от времени.

В обычном случае приходится брать исходник баннера и исправлять в нём ссылку, а потом компилировать баннер заново.

А хотелось бы иметь возможность изменить ссылку, на которую будет переводить баннер при клике, прямо из html-кода. Иными словами, передавать баннеру ссылку в виде параметра.

Как?

А вот как!

Подготовка flash-баннера

В сам баннер в первый кадр нужно добавить код для приёма параметра. А кнопку, которая осуществляет переход, изменить соответствующим образом.

Первый кадр flash-баннера

В него нужно добавить такой код:
// _level0.bannerLink is passed via FlashVars
if (_level0.bannerLink == undefined) {
	// Default link will be used if no other link was specified via params
	var bannerLink:String = "http://www.sprinthost.ru";
} else {
	var bannerLink:String = _level0.bannerLink;
}
bannerLink — это параметр, который будет передаваться в ролик. В коде также предусмотрена ссылка по умолчанию.

Код кнопки

Сама кнопка для клика получает следующий код:
on(release) {
    getURL(bannerLink);
}
На этом с самим роликом всё. Осталось ещё добавить собственно передачу параметра в html-код.

Добавление параметров баннера в код html

В тэг <object>, который используется для внедрения баннера, нужно будет добавить код, который выделен зелёным:
<object
  type="application/x-shockwave-flash"
  data="banner.swf"
  width="170" height="250">
    <param name="movie" value="banner.swf">
    <param name="wmode" value="transparent">
    <param name="allowScriptAccess" value="sameDomain" />
    <param name="FlashVars" value="bannerLink=http://www.google.com">
</object>
В данном примере ролику передаётся параметр, согласно которому он будет ссылаться на www.google.com.

Всё!

Поздравляю с достигнутым счастьем.
 
 
Хостинг-провайдер SPRINTHOST.RU запустил новый тарифный план «Та-Шу-Яотэ-Цай-Во-Ван-Ли». Говорят, дело было так:

Однажды к Основателям СПРИНТХОСТ.РУ в гости пришел их друг — мудрый восточный старец, которого все из почтения называли не иначе как Мастер. Старик хорошо разбирался в новых технологиях, поэтому Основатели не удивились, услышав его слова.

— Я хочу разместить у вас свои сайты, — сказал Мастер.

В этот день Основатели как раз разрабатывали новый тарифный план. Они знали, что Мастер ценит достаточность и с укоризной встречает излишества. Поэтому, выслушав старика, они не раздумывая предложили ему новый тариф, который слово в слово повторял пожелания Мастера.

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

— Та-Шу-Яотэ-Цай-Во-Ван-Ли!

— Как Вы сказали? — спросили Основатели.

Старец объяснил, что по-китайски это означает «У всех моих сайтов есть всё, что им нужно». В этот момент Основатели поняли, что ничто так хорошо не сможет отразить суть нового тарифного плана, как эти слова Мастера. Поэтому они решили назвать тарифный план «Та-Шу-Яотэ-Цай-Во-Ван-Ли».

Так и родился новый тариф компании СПРИНТХОСТ.РУ — тариф, на котором есть всё, что нужно: 3 сайта, 1 база данных, 2 гигабайта дискового пространства и мудрое слово Мастера. Стоимость тарифного плана «Та-Шу-Яотэ-Цай-Во-Ван-Ли» — 110 рублей в месяц.

Тариф доступен для заказа до 1 ноября 2008 года.
 
 
Как поставить Спамооборону 1024 Яндекса на FreeBSD с почтовым агентом exim? Сегодня я вплотную задался этим вопросом. Оказалось, что довольно просто, но и не без особенностей.

Спамооборона.Яндекса — это продукт для фильтрации спама от компании Яндекс. Правила фильтрации составляются на основании огромного количества писем, которое попадает на их почтовые сервера. Поэтому фильтры спама Спамообороны очень точно соответствуют реалиям российского почтового трафика. На самом деле Спамооборона.Яндекса — это лучший продукт для фильтрации спама, с которым мне приходилось работать.

Профессиональная версия Спамообороны стоит недёшево, однако существует бесплатная версия — Спамооборона 1024. Она подходит для серверов с небольшим количеством почтового трафика — 10000—20000 писем в сутки. Спамооборона 1024 проверяет письма, пока не наберётся 1024 не спамовых письма. После этого она начинает пропускать письма, пока сутки не истекут. Так как спама в среднем 90—95%, это позволяет проверить как раз 10000—20000 писем за день.

Установка Спамообороны 1024 на FreeBSD для exim требует некоторых усилий, потому что в документации описан совершенно верный метод подключения СО к exim, но он предполагает самостоятельную сборку exim. Более удобной же является сборка из портов, о которой и пойдёт речь.

Как это будет работать

Спамооборона 1024 подключается к exim через local scan. Никаких демонов на сервере устанавливать не требуется. При проверке письма Спамооборона 1024 соединяется с Яндексом по своему протоколу, отправляет туда копию письма и на основании ответа сервера Яндекса устанавливает заголовки X-Spam-Flag и X-Spam-Yversion. Баллы спама добавляются в поле «Subject» письма, если письмо сочтено спамом, например: «[SPAM 27.4] оригинальный сабджект». В X-Spam-Flag  указывается только YES или NO. Для того, чтобы иметь возможность настраивать изменение темы письма и видеть баллы в технических заголовках, необходимо воспользоваться профессиональной версией Спамообороны.

Получение Спамообороны 1024 для exim

В отличие от версий для других почтовых агентов, для которых предоставляются пакеты, для exim необходимо сказать исходник local_scan_1024.c. Для этого на странице загрузки Спамообороны 1024 необходимо выбрать в списке последний пункт "Исходный код для Unix (exim). Перед скачиванием файла необходимо будет заполнить нехитрую форму для учёта статистики загрузок.

Сборка exim из портов FreeBSD с включением Спамообороны 1024

Документация СО сообщает, что необходимо изменить Local/Makefile при сборке exim. Этого легко добиться, если exim собирается из исходников руками, но для сборки из портов придётся соблюсти определённую последовательность действий:

  1. cd /usr/ports/mail/exim/;
  2. make configure;
  3. правка work/exim-4.69/Local/Makefile в соответствии с документацией СО;
  4. перегенерация makefile: cd work/exim-4.69/ ; make makefile;
  5. продолжение сборки и установка: cd /usr/ports/mail/exim/ ; make install;
  6. создание папки для работы Спамообороны: mkdir -p /var/spool/spamooborona; chown mailnull /var/spool/spamooborona (если exim будет работать от пользователя mailnull).

Но это не всё. Текущая версия порта exim (4.69) заменяет в Local/Makefile опцию LDFLAGS на свою хитровыдуманную DUMMY_LDFLAGS и в дальнейшем использует только её. Так как мы добавляем LDFLAGS в Local/Makefile уже после make configure, наш LDFLAGS не обнаруживается при дальнейшей сборке, и exim с СО не собирается из-за отсутствия подключённых библиотек.

Решения два:
  • вместо LDFLAGS прописывать в Local/Makefile опцию DUMMY_LDFLAGS (не лучшее решение);
  • добавлять LDFLAGS в качестве аргумента make таким образом: make LDFLAGS+=-lz install (решение, достойное существования).
После этого Спамооборона 1024 успешно включается в exim и может проверять почту.

Проверка успешности сборки

Для того, чтобы проверить, действительно ли СО включена в exim, необходимо выполнить команду:
strings /usr/local/sbin/exim | grep sp-exim
Если что-то есть, значит, СО включена в бинарник.

Автоматизация сборки

Для автоматической сборки exim со Спамообороной 1024 я написал скриптик:
#!/bin/sh

EXIM_VER=4.69
SO_LOCAL_SCAN=/root/tools/inst-tools/exim/SO/local_scan_1024.c
INSTALL_PREFIX=/usr/local/experimental/exim-so1024/
EXIM_USER=mailnull

OPTS="
PREFIX=$INSTALL_PREFIX
-D WITH_CONTENT_SCAN -D WITHOUT_IPV6
-D WITHOUT_OLD_DEMIME
-D WITHOUT_NIS
"

[ "$1" = "opts" ] && echo $OPTS && exit

cd `dirname $0`
WRKDIR=$PWD

cd /usr/ports/mail/exim
make clean
make $OPTS configure

cat >> work/exim-$EXIM_VER/Local/Makefile <<EOF
LOCAL_SCAN_SOURCE=Local/local_scan_1024.c
EOF

cp $SO_LOCAL_SCAN work/exim-$EXIM_VER/Local/

cd work/exim-$EXIM_VER
make makefile
cd ../../

make LDFLAGS+=-lz $OPTS -D NO_PKG_REGISTER install

mkdir -p /var/spool/spamooborona
chown $EXIM_USER /var/spool/spamooborona


В скрипте необходимо указать версию exim, префикс для установки, путь до local_scan_1024.c и пользователя exim (для установки прав на /var/spool/spamooborona). Также можно в OPTS перечислить опции порта exim для сборки.

В make install используется -D NO_PKG_REGISTER, чтобы можно было многократно переустанавливать exim без make deinstall && make reinstall и ставить различные его версии в различные префиксы. Правда, тогда exim не будет виден в pkg_info.

Успешной фильтрации спама (со Спамообороной это достигается очень легко :)!
 
 
Сегодня мне пришлось составлять довольно хитрый редирект: если пользователь запросил /news/some-section/, то его нужно было перенаправить на просто /section/, но потом всё равно сделать внутренний редирект на /news/some-section/, так как сам движок новостей лежит именно там.

Я написал простое правило, обновил страничку... и получил от mod_rewrite по полной программе, потому что он ушёл в бесконечный цикл и не собирался из него возвращаться. Я открыл документацию и начал разбираться. Потом включил RewriteLog. Сначала я был озадачен. Потом стал откровенно злиться. А к тому моменту, когда задача была решена, я успел пережить такое количество разных чувств, что кроме равнодушного вздоха ничем больше не смог отметить достигнутый результат.

Оказывается, mod_rewrite называют вуду не потому, что он волшебный. А потому что для того, чтобы осознать, как он работает, нужно три раза прочитать по нему документацию. Вслух. С выражением! Потом найти все параграфы, начинающиеся со слова "Note" и пересказать их своими словами. Потом нужно найти все параграфы, в которых больше одного предложения и тоже пересказать их своими словами. Тоже вслух. И с выражением тоже.

Но и это ещё не всё. После этого нужно пойти по ссылке "detailed mod_rewrite documentation" и почитать там. А потом отправиться впитывать полезный опыт в гугл.

Так много слов выше написано оттого, что сам я только что всё это проделал и мне нужно высказаться. Вы, наверное, думаете - ну и где же обещанное "как на самом деле"? Подождите, сейчас расскажу.

По работе мне приходится составлять довольно простые правила, зато их довольно много. Приходится следить, чтобы они не пересекались друг с другом. Директив использую немного - RewriteCond, RewriteRule и флаги [L], [R], изредка [NC] и [QSA]. Без усложний с map'ами, chain'ами и subreq'ами.

Опыт программирования подсказывал мне (и некоторые другие программисты были со мной согласны), что если я сказал [R], то в этом месте должен начаться редирект. А если указано [L], то разбор правил должен прекратиться (совсем-совсем прекратиться). Ну и когда все правила пройдены, разбор прекращается, отдаётся скрипт, на который смотрит получившийся адрес.

Ага. Щаз.

Оказывается, всё работает несколько иначе.

[R] на самом деле не делает редирект. Он просто делает текущий адрес абсолютным (дописывает к нему http://хост/) и где-то себе запоминает, что потом нужно будет сделать внешний редирект. После этого разбор правил продолжается до конца .htaccess, и вот уже тут происходит перенаправление.

[L] на самом деле не останавливает полностью разбор правил.
Если разбор происходит в .htaccess (как это обычно бывает), то совершается переход в конец .htaccess, и вот тут уже... происходит перенаправление? Ну да, только в его результате мы с большой вероятностью опять попадаем на тот же .htaccess, и начинается проход по всем правилам заново (даже при внутреннем редиректе!). И этот цикл будет продолжаться до тех пор, пока не настанет момент, когда ни одно правило не сработает (или пока мы редиректом не выйдем из директории, в которой лежит наш .htaccess). Вот тогда уже сервер отдаст страничку.

Единственно предсказуемое поведение дают [R,L] вместе взятые. В этом случае отмечается, что должен произойти редирект, пропускаются все следующие правила и юзеру отдаётся перенаправление на указанную страницу.


Какой из этого вывод? Не надо везде подряд ставить [L]. Если, конечно, хотите понимать, в каком порядке обрабатываются правила. Если [L] нигде не указан, то проход осуществляется строго подряд. Правда, когда правила закончатся, и окажется, что какое-то из них поменяло ссылку, всё равно будет запущен проход по всем правилам ещё раз. Но это уже гораздо проще контролировать.

Например. Обычно ссылка после изменения не подходит под то же или под какое-либо другое правило. То есть, если вы перенаправляете /news в index.php/news:

RewriteRule ^news/$ index.php/news

то второй раз это правило уже не сработает.

Однако в моём случае нужно было запрос пользователя /news/section-name/ перенаправлять в /section-name/, а потом делать внутренний редирект обратно с /section-name/ на /news/section-name/, где находился обработчик новостей. То есть:

RewriteRule ^news/section-name/$ section-name/ [R=301,L]
RewriteRule ^section-name/ news/section-name/

Первый редирект внешний, второй внутренний. Если бы всё происходило в один проход, всё было бы нормально. Но так как проходы длятся пока срабатывает хотя бы одно правило, происходило следующее. Пользователь набрал /news/section-name/. Его внешним редиректом перенаправило на /section-name/. Потом сработало второе правило и произошёл внутренний редирект на news/section-name/. Потом mod_rewrite обнаружил, что ссылка изменилась, и инициировал повторную обработку запроса. Опять сработало первое правило, пользователь получил внешний редирект. Круг замкнулся.

Для того, чтобы разрешить внешний редирект только в том случае, если запрос /news/section-name/ прислан пользователем, а не сгенерирован RewriteRule, приходится проверять %{THE_REQUEST}:

RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /news/section-name/
RewriteRule ^news/(.*) /$1 [R=301,L]

Работает: после внешнего редиректа пользователь запрашивает /section-name/, этот запрос попадает в THE_REQUEST и для первого правила не выполняется RewriteCond.

За информацию спасибо следующим ссылкам:

* http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
* http://www.askapache.com/htaccess/mod_rewrite-basic-examples.html
* http://httpd.apache.org/docs/2.2/rewrite/rewrite_tech.html
 * http://www.google.com

Там написано, почему при обработке правил в .htaccess происходят повторные запросы с повторным проходом по всем правилам, и почему при указании директив редиректа в <VirtualHost> или в глобальном конфиге Apache не в разделе <Directory> проход происходит только один раз.
 
 
Дорогие друзья.

В связи с тем, что меня не устраивает политика AOL в отношении сторонних клиентов icq, я принял решение покинуть ICQ, а всем своим друзьям советовать jabber. Мой JabberID - cronfy@gmail.com, он же мой почтовый адрес для связи по электронной почте.

Для того, чтобы подключиться к Jabber, достаточно зарегистрировать аккаунт Gmail. У Google есть замечательная подробная инструкция о настройке Jabber для аккаунта Gmail для различных IM-клиентов (английский вариант полнее, чем русский).

Джаббер. кстати, ещё и шустрее работает. А в статье "Вперед в будущее! Переход с ICQ на Jabber" подробно рассказывается о невероятных преимуществах этого протокола перед ICQ и о других способах подключения к Jabber. Там же описывается методы, позволяющие сохранить связь с существующими контактами ICQ через джаббер.
 
 
Проведя несколько последних дней в борьбе и информерами, которые должны размещаться на партнёрских сайтах, пришёл к выводу, что полученный опыт стоит того, чтобы его не забыть.

Информеры - это когда на сайте есть новости,  и хочется блоки со свежими новостями размещать на сайтах-партнёрах для привлечения трафика.

Чеклист получился довольно недлинный:
  • единая структура;
  • стили: префикс для названий классов, общий класс и раздельные классы для представлений;
  • разные форматы;
  • кодировка может быть разной;
  • ссылки наружу и таргет;
  • аргументы для модификации информера;
  • показ X новостей из последних X*2 новостей.
Ниже обо всём подробнее.

Структура


В целом структуру целесообразно делать одинаковой для всех вариантов представления. В крайнем случае, если определённый стиль информера не предполагает блока текста, можно отдать пустой параграф, но структуру лучше сохранить. Это избавит от неожиданностей при желании "немного поменять css", а также сделает возможным полностью отцепить всё оформление от самого информера и положить его в отдельную css'ку. Когда точно знаешь, что все информеры одинаковые внутри, это воодушевляет (вообще-то, когда что-то знаешь точно, это всегда воодушевляет ;).

Стили

Всё внешнее представление выносится в стили. Особое внимание нужно обратить на названия классов - они должны начинаться с какого-либо префикса, чтобы не смешаться со стилями сайта, на котором размещается информер. Общий для всех представлений класс можно назвать my-site-informer, а классы различного оформления - my-site-informer-compact, my-site-informer-full, my-site-informer-horiz и так далее. Довольно длинно, зато если на сайте партнёра два информера с вашего сайта, выполненные в разных стилях, их классы не перемешаются в неразборчивую кашу.

Формат

Нужно предусмотреть возможность получения информера как минимум в html и в виде ява-скрипта (достаточно document.write, главное не забыть заэскейпить "\r", "\n" и "'"). Случаи бывают разные.

Кодировка


Это удивительно, но на сайтах-партнёрах может быть кодировка, отличная от использующейся на вашем сайте UTF-8 ;) Необходимо предусмотреть возможность через аргументы в ссылке или каким-либо другим способом задать желаемую кодировку информера. windows-1251, utf-8... пожалуй, хватит.

Ссылки

Ссылки должны быть абсолютными. У ссылок должен быть _target. Это выглядит очевидным, но об этом легко забыть в порыве побыстрее посмотреть на результат и покликать по ссылкам.

Другие аргументы

Довольно удобно, если аргументами в ссылке можно задать количество новостей в информере. Стандартные блоки по 3. 5, 10 новостей - это отлично, но есть люди, которым нравятся другие числа ;-)

Если на сайте несколько разделов новостей, довольно просто сделать так, чтобы можно было лёгким изменением ссылки выбрать любой из них. Информер для двадцати разделов пишется так же, как и информер для одного, разница только в одной переменной. А партнёрам приятно.

Разброс новостей


Информер из пяти блоков показывает пять самых свежих новостей. Но менее свежим новостям, которые не влезают в блок, от этого становится скучно. Можно исправить эту ситуацию, показывая в пяти новостях две самые свежие новости, и три выбирая случайным образом из десяти последних.

Ну и примеры


css:

/* common style */

div.mysite-informer {
width: 100%;
text-align: left;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
div.mysite-informer * {
margin: 0; padding: 0; border: 0; float: none;
line-height: 100%; color: black;
}


/* hotline style */

div.mysite-informer-hotline div.mysite-informer-post {
float: left; width: 20%; text-align: center;
}
div.mysite-informer-hotline div.mysite-informer-post p.mysite-informer-description {
padding: 5px 0.5em; margin: 0; font-size: 12px;
}
div.mysite-informer-hotline img {
 border: none; width: 125; height: 93;
}
div.mysite-informer-hotline a.mysite-informer-morelink {
display: none;
}
div.mysite-informer-hotline div.mysite-informer-post p.mysite-informer-date {
display: none;
}
div.mysite-informer-hotline div.mysite-informer-post h3 {
display: none;
}

html:

<div class="mysite-informer mysite-informer-hotline">
<div class="mysite-informer-post">
<a href="http://www.example.com/news/new-year-of-orange-sky.html">
<img src="http://www.example.com/images/news/10928-thumb.gif"
 alt="Orange sky with birds" />
</a>
<p class="mysite-informer-description">
Orange sky gets more than just a few clouds up there
<a href="http://www.example.com/news/new-year-of-orange-sky.htm"
class="mysite-informer-morelink">
подробнее »
</a>
</p>
</div>
</div>

Ссылка для получения информера из раздела сайта miracle
с 7-ю блоками новостей:

http://www.example.com/informer/miracle.js?style=hotline&charset=windows-1251&qty=7

 
 
Помимо написания скриптов на php, сегодня я также задался вопросом, каким образом можно в Linux набирать Unicode-символы (как <Alt> + 0151 для длинного тире в Windows). Alt с кодом у меня не заработал (то ли из-за ноутбучной клавиатуры, то ли Linux так не умеет), и я решил со злости погуглить.

Практически сразу мне на глаза попалась хорошая статья о вводе символов Unicode в Linux. Вместо номера символа используются последовательности вроде <Win> + --- для длинного тире, <Win> + >> для правой «ёлочки», и т. д. Причём вместо Win можно назначать <Ctrl>, <Alt> или даже <Caps Lock>. Конечно, все символы так не введёшь, но популярные вводить довольно удобно, и последовательности легко запоминаются.

Кстати, в SuSE под KDE такое поведение настраивается одной галкой (Оборудование -> Раскладка клавиатуры -> Настройки -> в длинном списке раздел "Расположение клавиши последовательности"). Работает даже в mcedit, честное слово.