Как обойти защиту от хотлинкинга

Давненько я не писал чего-нибудь общественно-бесполезного. На одном из популярных форумов люди постят картинки с сайтов, которые не хотят, чтобы их смотрели где-то еще. А вбивать чужой урл и идти на страницу с картинкой иногда бывает лень. Поэтому, чтобы такой посмотреть, надо либо подделать реферер (с помощью какого-либо плагина к браузеру), либо воспользоваться моим новым сервисом просмотра картинок с защитой от хотлинкинга.

Работает это как прокси-сервер, скрипт забирает картинку и отдает ее тому, кто ввел капчу. Вроде несложно и кому-то может пригодиться. Кстати, вручную реферер вбивать не обязательно, скрипт попытается его вычислить. Но надежности ради я предусмотрел возможность добавления реферера вручную. Проверить можно хотя бы на этом примере.

Если найдете багу, просьба писать в камменты здесь или напрямую написать мне

З.Ы. Сервис абсолютно бесплатный

Кириллические домены и iDNS

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

Даже самый известный кириллический домен президент.рф и тот толком не распознается некоторыми серверами. Публичные DNS сервера Google о нем что-то знают:

dig xn--d1abbgf6aiiy.xn--p1ai @8.8.8.8

; <<>> DiG 9.6.1-P3 <<>> xn--d1abbgf6aiiy.xn--p1ai @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61712
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;xn--d1abbgf6aiiy.xn--p1ai. IN A

;; ANSWER SECTION:
xn--d1abbgf6aiiy.xn--p1ai. 564 IN A 195.208.24.91

;; Query time: 75 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Wed Dec 1 17:29:40 2010
;; MSG SIZE rcvd: 59

А вот один из корневых серверов DNS не знает ничего:

dig xn--d1abbgf6aiiy.xn--p1ai @4.2.2.2

; <<>> DiG 9.6.1-P3 <<>> xn--d1abbgf6aiiy.xn--p1ai @4.2.2.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 20017
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;xn--d1abbgf6aiiy.xn--p1ai. IN A

;; Query time: 78 msec
;; SERVER: 4.2.2.2#53(4.2.2.2)
;; WHEN: Wed Dec 1 17:29:49 2010
;; MSG SIZE rcvd: 43

Что касается зон iDNS (.ком, .нет, .орг), так они вообще мало кому доступны. Регистраторы (Webnames.ru) например предлагают воспользоваться какой-то говнософтиной вроде iChat, чтобы ваш компьютер смог нормально работать с такими доменами. Вот кому надо чего-то скачивать и ставить себе? Мало кто будет это делать.

На самом деле этот говнософт никому не нужен. Все, что надо, чтобы ресолвились доменные зоны .ком, .нет и .орг, это всего лишь прописать у себя правильный iDNS сервер, вместо DNS провайдера. На idns.net есть файл (db.cache) с корневыми серверами iDNS, можно один из них использовать вместо DNS провайдера:

> cat /etc/resolv.conf
nameserver 64.62.142.131 # iDNS
nameserver 195.161.113.189 #iDNS
nameserver 120.50.44.141 #iDNS

Но на самый правильный способ я натолкнулся на блоге ihtiandr.info, надо интернет провайдерам настроить свои DNS-сервера примерно вот так, и тогда ни у кого не будет геморроя с кириллическими доменами.

OpenSuSe 11.3, D-Link DWA 525 и танцы с бубном

D-Link DWA 525, сетевая карта с WiFi

Моя домашняя сеть продолжает расти, и мне потребовалось подключить еще один компьютер к моей точке доступа D-Link DWL 2100 AP. Посмотрев на прайс-листы ближайшего приличного магазина, присмотрелся я к сетевой карте с антенной – а именно к D-Link DWA 525. Традиционно погуглил эту карту на предмет наличия проблем с установкой под линуксом – вроде все чисто, решил купить. И тут началось….

Под Windows XP она встала и работает неплохо, но с картой совершенно не было драйверов под линукс. Свежепоставленная OpenSuSe 11.3 так же карточку не опознала как сетевую, пришлось качать драйвер с сайта dlink.ru и собирать его.

Дальше было еще интереснее, драйвер от dlink собрался, но карта работала только с открытыми сетями, без WEP или WPA шифрования. Разумеется, меня такой вариант не устроил, стал искать другое решение проблемы. Оказалось, что драйвера от d-link – это совсем не то, что нужно. Для карты D-Link DWA 525 прекрасно подошел последний драйвер от карты на том же чипсете (Ralink 3060, последнюю версию драйвера можно скачать с официального сайта: http://www.ralinktech.com/support.php?s=2).

Однако и тут обошлось не без танцев с бубном. Перед компиляцией драйвера надо залезть в файл os/linux/config.mk и поправить 2 строчки:

HAS_WPA_SUPPLICANT=y
HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y
(эти фичи выключены по умолчанию).

После сборки драйвера (make и make install) все замечательно заработало бы, если бы не ошибка в скрипте /etc/sysconfig/network/scripts/ifup-wireless Вместо этого глючного скрипта следует скачать исправленный скрипт, и только тогда все заработает, как надо.

Все вышесказанное относится к OpenSuSe 11.3 без обновлений (из коробки). Возможно, что после обновления этот скрипт уже будет пропатчен

Data::Dumper и текст в UTF-8

Если вы работаете со сложными структурами данных (массивы хешей, хеши массивов и т.п.), наверняка вы используете для отладки модуль Data::Dumper. Все бы хорошо, но этот модуль категорически не хочет работать с символами в кодировке UTF-8, его вывод выглядит примерно так:

'country' => "\x{420}\x{43e}\x{441}\x{441}\x{438}\x{44f}",
'city' => "\x{41c}\x{43e}\x{441}\x{43a}\x{432}\x{430}",
'airport' => "\x{414}\x{43e}\x{43c}\x{43e}\x{434}\x{435}\x{434}\x{43e}\x{432}\x{43e}",
'code' => 'DME'

Чтобы сделать вывод функции Dumper читаемым, надо просто добавить в программу вот такой кусочек кода:

$Data::Dumper::Useqq = 1;

{ no warnings 'redefine';
sub Data::Dumper::qquote {
my $s = shift;
return "'$s'";
}
}

Тогда вывод будет выглядеть совсем по другому:

'country' => 'Россия',          
'city' => 'Москва',
'terminal' => '',
'airport' => 'Домодедово',
'code' => 'DME'

Как наложить субтитры на видео

ОС: Opensuse 11.2
Софт: mplayer, mencoder (freeware)

Mplayer сам по себе достаточно умный, чтобы добавлять субтитры из внешнего файла к готовому видео. К примеру, есть у меня файл Madagascar – Escape 2 Africa.avi, и к нему идет текстовый файл с субтитрами – Madagascar – Escape 2 Africa.srt с расписанием, на какой секунде какой текст показывать. При запуске mplayer автоматом цепляет файл с субтитрами и все прекрасно работает.

Но сложности начинаются, если файл с субтитрами переименовать – тогда они не будут видны. Чтобы избежать таких неприятностей, всегда можно перекодировать фильм с добавлением субтитров с помощью mencoder:

mencoder -oac copy -ovc lavc -lavcopts keyint=25:vcodec=mpeg4:vbitrate=679:vpass=1 -sub “Madagascar – Escape 2 Africa.srt” -o “Madagascar – Escape 2 Africa.with.subtitles.avi” “Madagascar – Escape 2 Africa.avi”

Кстати, mencoder еще и умеет вырезать кусочки видео из общего фильма. Чтобы вырезать 74 секунды видео с 1000-й секунды воспроизведения, надо просто указать эти параметры:

mencoder -oac copy -ovc lavc -lavcopts keyint=25:vcodec=mpeg4:vbitrate=679:vpass=1 -ss 970 -endpos 74 -sub “Madagascar – Escape 2 Africa.srt” -o “Madagascar – Escape 2 Africa.en.with.subtitles.avi” “Madagascar – Escape 2 Africa.avi”

Вот такой ролик у меня получился (смотреть всем, а особенно тем, кто тренируется воспринимать английскую речь на слух). Встроить ролик в страницу не получилось, потому что Youtube ограничил показ этого ролика для ряда стран (Россия в этот список не попала)

Похожие посты:
Как пережать 3gp в avi, Как скачать видео с сайта, Как сделать видеоклип из фотографий

Update: Youtube заблокировал показ этого ролика. Интересное кино….

Эффект черного ящика

Многие программисты на Perl частенько используют модуль XML::Simple для обработки файлов. Казалось бы, что может быть проще, чем распарсить файл:

use XML::Simple;
my $xs = XML::Simple->new();
my $ref = $xs->XMLin(‘test.xml’);

Однако даже такой простой кусок кода в разных системах реагировал по-разному на один и тот же исходный файл. Если в исходном файле XML встречались символы в кодировке utf8, скрипт мог свалиться на этапе разбора файла.

Выяснилось, что модуль XML::Simple сам по себе не занимается разбором XML, и парсинг происходит с помощью других доступных модулей. Если в системе установлен XML::SAX, то именно он будет использоваться по умолчанию, в противном случае для разбора будет применяться XML::Parser.

С XML::SAX тоже не все просто, он для разбора использует либо XML::SAX::PurePerl (что медленно и не всегда корректно работает), либо XML::SAX::Expat или XML::SAX::ExpatXS (если они установлены).

Так вот, чтобы XML::Simple смог корректно разобрать XML файл со строками в кодировке UTF-8, надо установить XML::SAX::Expat или XML::SAX::ExpatXS. Это совершенно не очевидно, и об этом можно забыть при переносе скриптов с сервера на сервер.

Как сделать видеоклип из фотографий

Дано: несколько фоток и подходящая музыка.
Требуется: сделать из них простенький клип.
Софт: mencoder (freeware)

Чтобы нормально все выглядело, нам надо знать продолжительность музыкального трека в секундах и количество фотографий. В моем случае трек был на 132 секунды, и у меня было 14 фоток. Получается, чтобы равномерно их показать, смена кадров должна происходить один раз в 9,43 секунды (132 / 14). Соответственно, FPS (Frames Per Second) для ролика составит (14 / 132) = 0,106

Ну и получить клип можно одной командой:

mencoder mf://*.jpg -mf fps=0.106 -ovc lavc -lavcopts vcodec=mpeg4 -audiofile theme.mp3 -oac mp3lame -lameopts abr:br=160 -srate 44100 -ofps 25 -o output.avi

Мне, как и любому программисту, лениво руками считать количество файлов и продолжительность музыкального трека. Поэтому я cваял простенький скрипт на Perl, который и делает за меня эту грязную работу:

#!/usr/bin/perl -w
use MP3::Info;
my $mask = "*.jpg";
my @pics = glob($mask);
my @sounds = glob("*.mp3");
my $a = get_mp3info($sounds[0]);
my $seconds = $a->{'SECS'};
my $pics_number = $#pics + 1;
my $FPS = $pics_number / $seconds;
my $cmd = "mencoder mf://".$mask." -mf fps=".$FPS." -ovc lavc -lavcopts vcodec=mpeg4 -audiofile ".$sounds[0]." -oac mp3lame -lameopts abr:br=160 -srate 44100 -ofps 25 -o output.avi";
my $res = system($cmd);

И вот что у меня получилось:

Копирайты: фотки мои, музыка The Dead Rocks, One Million Dollar Theme.

Еще по теме: Как пережать 3gp в avi, Как скачать видео с сайта, Мои путешествия – избранное

Настройка Триколор Интернет в OpenSuSe 11.2

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

Используемое оборудование: DVB Карта Prof Revolution 7301 S2 и ADSL модем D-Link 500T в режиме роутера. Операционная система OpenSuSe 11.2.

1: Регистрация оборудования в личном кабинете. Вносим MAC-адрес DVB-карты, получаем IP адрес, логин и пароль.

Каждую цифру полученного IP адреса переводим в шестнадцатеричный вид, и получаем новый MAC-адрес устройства вида МАС 00:02:XX:XX:XX:XX (подробности здесь). Он будет нужен для создания VPN соединения.

2. Создаем VPN соединение любым способом. Кто-то делает через Yast (настройка DSL), кто-то делает через kvpnc; я же сделал через pptp-command, создал новый CHAP secret, создал новый pptp-туннель и не трогал маршрутизацию. Добился того, чтобы при запуске pptp-command start создавалось соединение (через устройство ppp0), и убивалось по команде pptp-command stop.

3. Настраиваем прием данных со спутника, используя IP сервера 81.177.31.194, и логин с паролем из личного кабинета. Создаем файл /etc/tricolor.conf с одной единственной строчкой:

Trikolor:11766:h:0:27500:1000:1000:0

В /etc/resolv.conf указываем любые публичные DNS-сервера:

nameserver 8.8.4.4 
nameserver 4.2.2.2
nameserver 8.8.8.8

Выкладываю свой скрипт, который у меня лежит в /etc/init.d/tricolor.sh :

#!/bin/bash                                                                  

PATH=/usr/sbin:/usr/bin:/sbin:/bin
NAME=`basename $0`

# https://cabinet.stv.su/index.php?m=info
IP="192.168.100.1" #Сюда прописываем ваш IP-адрес, (адрес левый, роли не играет)
MAC="00:02:XX:XX:XX:XX" #сюда пишем MAC-адрес сконвертированный из IP адреса данного триколором
PID="0x3e8" #здесь должен быть ваш PID (можно и в dec) 0x3e8h=1000d

# https://cabinet.stv.su/index.php?m=conf

CHANNELS_CONF="/etc/tricolor.conf"

# http://forum.stv.su/viewtopic.php?t=1173
case "$1" in
start)
echo "starting $NAME..."
#Теперь отключим rp_filter, фильтрующий пакеты которые не могут уйти через тот же интерфейс что и пришли
/sbin/sysctl -w net.ipv4.conf.all.rp_filter="0"
/sbin/sysctl -w net.ipv4.conf.default.rp_filter="0"
#сие так замудренно всвязи с проблемамаи на ядре 2.6.24 и выше
/usr/sbin/pptp-command start
dvbnet -p $PID
szap -l 10750 -c $CHANNELS_CONF -n 1 > /dev/null &
ifconfig dvb0_0 hw ether $MAC
ifconfig dvb0_0 $IP
route add -net 0.0.0.0 dev ppp0
;;
stop)
/usr/sbin/pptp-command stop
echo "stoping $NAME..."
ifconfig dvb0_0 down
dvbnet -d 0
killall szap #ну раз замудрили при старте, мудрим и при остановке - иначе никак =(
/etc/init.d/network restart
;;
restart)
$0 stop
$0 start
;;
*)
echo "usage: $NAME start|stop|restart"
exit 3
;;
esac

exit 0

Для карт S2 есть принципиальный момент, MAC адрес должен назначаться до назначения IP, иначе скрипт будет ругаться на невозможность назначить айпишник устройству. Последняя строчка в секции start заворачивает весь исходящий трафик на VPN.

Далее от рута даем команду /etc/init.d/tricolor.sh start и все заработало.

Как видно из скрипта, при поднятии VPN запросы на сервера DNS и будут отправляться через ADSL-модем (через устройство ppp0), весь входящий трафик пойдет через спутниковую DVB карту. Проверить это можно, если запустить ifconfig:

# ifconfig
dvb0_0 Link encap:Ethernet HWaddr 00:02:XX:XX:XX:XX
inet addr:192.168.100.1 Bcast:192.168.100.255 Mask:255.255.255.0
UP BROADCAST RUNNING NOARP MULTICAST MTU:4096 Metric:1
RX packets:455 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:168998 (165.0 Kb) TX bytes:0 (0.0 b)
Base address:0x3e8

eth1 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX
inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:106749 errors:0 dropped:0 overruns:0 frame:0
TX packets:127707 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:40869070 (38.9 Mb) TX bytes:25464396 (24.2 Mb)
Interrupt:19 Base address:0x8000

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:50 errors:0 dropped:0 overruns:0 frame:0
TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3340 (3.2 Kb) TX bytes:3340 (3.2 Kb)

ppp0 Link encap:Point-to-Point Protocol
inet addr: XX.XX.XX.XX P-t-P:10.1.1.1 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:996 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:485 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:80 (80.0 b) TX bytes:58760 (57.3 Kb)

Таблица маршрутизации у меня выглядит так:

# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
81.177.31.194 192.168.1.1 255.255.255.255 UGH 0 0 0 eth1
10.1.1.1 * 255.255.255.255 UH 0 0 0 ppp0
192.168.100.0 * 255.255.255.0 U 0 0 0 dvb0_0
192.168.1.0 * 255.255.255.0 U 0 0 0 eth1
link-local * 255.255.0.0 U 0 0 0 eth1
loopback * 255.0.0.0 U 0 0 0 lo
default * 0.0.0.0 U 0 0 0 ppp0
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth1

Все замечательно работает. Правда, скорость скачивания через tricolor internet раз в 10 меньше скорости скачивания через ADSL модем, но зато у меня появился дополнительный айпишник из триколоровской сети.

Апгрейд MySQL и переписывание запросов

Официальный логотип Mysql

Технически апгрейд базы MySQL несложен, но могут возникнуть не очевидные подводные камни. Например, если MySQL был 4-й версии, а после upgrade версия стала выше 5.0.11, то могут возникнуть проблемы с работой запросов, использующих LEFT JOIN.

Начиная с версии MySQL 5.0.12 запросы с JOIN обрабатываются по стандарту SQL:2003, поэтому такие запросы к базе придется переписать. Вот пример:

CREATE TABLE IF NOT EXISTS `t1` (
`id` int(10) unsigned NOT NULL auto_increment,
`type` enum('a','b') default NULL,
PRIMARY KEY (`id`),
KEY `type` (`type`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `t1` VALUES (1, 'a'), (2, 'a'), (3, 'b'), (4, 'a'), (5, 'b');

CREATE TABLE IF NOT EXISTS `t2` (
`t1_id` int(10) unsigned default NULL,
KEY `t1_id` (`t1_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `t2` VALUES (1), (1), (1), (2), (2);

CREATE TABLE IF NOT EXISTS `t3` (
`t1_id` int(10) unsigned default NULL,
KEY `t1_id` (`t1_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `t3` VALUES (1), (1), (2), (2), (3);

#Test 1
select t1.id
from t1, t2
left join t3 on t1.id = t3.t1_id and t1.type = 'a'
where t1.id = t2.t1_id
group by t1.id
#1054 - Unknown column 't1.id' in 'on clause'

#Test 2, swap the order of the conditions in "on"
select t1.id
from t1, t2
left join t3 on t1.type = 'a' and t1.id = t3.t1_id
where t1.id = t2.t1_id
group by t1.id
#1054 - Unknown column 't1.type' in 'on clause'

В MySQL 4.x запрос работает без ошибок, начиная с версии 5.0.12 запрос ругается на синтаксис. Если в эти запросы добавить скобок, все заработает:

select t1.id
from (t1, t2)
left join (t3) on (t1.id = t3.t1_id and t1.type = 'a')
where t1.id = t2.t1_id
group by t1.id

select t1.id
from (t1, t2)
left join (t3) on (t1.type = 'a' and t1.id = t3.t1_id)
where t1.id = t2.t1_id
group by t1.id

Выбираем видеокарту

ATI Radeon HD 5570, отличная видеокарты

Так получилось, что моя видеокарта ATI Radeon X1650 сдохла, проработав почти 3 года. К ней особых претензий не было, и я таки решил выбрать себе видюху того же производителя на замену убитой. Одним из основных требований к карте у меня была возможность просмотра HDTV в формате h.264, ну и невысокая цена. Мой выбор пал на карточку ATI Radeon HD 5570, стоит она примерно $85 и втыкается в тот же слот PCI Express, что использовался ныне покойной видюхой.

Карта тупо втыкается в маму, ставятся драйвера от производителя ATI — и вуаля, все работает. Xorg 7.4 достаточно умный, чтобы определить новое железо и нормально его использовать без изменения каких-либо конфигурационных файлов.

Решил я погонять игрушки протестировать производительность новой видеокарты в условиях максимальных нагрузок. Перепробовал много 3D вещей, доступных под линуксом – Quake3, TileRacer, Supertuxcart, Etracer и т.п. – все работает без нареканий.

Эти карты очень свежие, на рынке появились в феврале 2010 года. Убежден, что подлянки с прекращением выпуска драйверов для новых версий Xorg для этой карты ожидать в ближайшее время не стоит.