Saturday, February 20, 2010

Авторизатор для моего ISP (Обработка HTML в Python)

Предыстория.
После весьма болезненного перехода на нового провайдера Интернет, появилась задача написать авторизатор. Дело в том что провайдер дает возможность доступа к сети двумя способами:
  1. с помощью специальной программки, которая написана для ОС Windows. Програмка совсем неплохая и даже отлично работает под Wine (разве что криво русские шрифты отображаются).
  2. с помощью авторизаци через web browser. Происходит это примерно так: пользователь заходит на сайт провайдера (который всегда доступен), вводит в нужные формы логин и пароль. В последствии загружается страница, что обновляется через каждые 40 сек. Конечно же если мы закроем страницу, то по истечении 40 сек. доступ в Интернет оборвется.
Решил попробовать свои силы в написании скрипта авторизации, использовать попробую Python. Я совсем не эксперт в этой области и далеко от уверенного пользователя, потому наличие не оптимально написанного кода почти гарантировано.
Задача
Необходимо написать скрипт, который бы автоматически генерировал ссылку для авторизации (по данным взятым с страници провайдера) и каждые 40 секунд делал запрос по этой ссылке.
Разбор полетов
После того как в нужные формы пользователь ввел данные формируется ссылка следующего формата:
http://stat.pautina-nau.net/cgi-bin/stat.pl?ses=11111111&a=98&uu=111111&pp=123456789abcdef123456789abcdef00
? - указывает конец ссылки и дальше передаются переменные.
& - разлелитель между переменными.
Какие выводы?
  1. скрипт который обрабатывает данные stat.pl
  2. переменная с именем пользователя (логином) uu.
  3. Переменная котороая содержит пароль pp.
  4. Неизвестная переменная со значением a=98
  5. Неизвестная переменная со значением ses=11111111
Посмотрим в как это описывается в разметке страницы? Для начала просмотрим
страницу в которой находятся формы для логина и пароля:

<form method=get action='/cgi-bin/stat.pl' onsubmit='pp.value=hex_md5(ses.value+" "+pp.value); return true'>
<input type=hidden name=ses value=201110>
<table class='tbg1'><tr class='head'><td align=center colspan=3>
<input type=hidden name=a value=98>Если вы хотите получить доступ в интернет без 
авторизатора - авторизуйтесь в этом окне. 
После авторизации не закрывайте окно - оно будет периодически авторизовываться на 
сервере и поддерживать открытым доступ в интернет</td></tr>
<tr class=row2><td align=right width='33%'>Логин:</td><td><input type=text name=uu size=25 value='' tabindex=4></td> <td rowspan=2 class=row2>
<input type=submit value=' Авторизоваться ' tabindex=6></td></tr><tr class=row2> <td align=right>Пароль:</td>
<td><input type=password name=pp size=25 value='' tabindex=5></td></tr></table>
Этот кусок исходного кода страницы содержит информацию о интересных для нас формах: логин, пароль и формирователья запросов. Рассматривать код начнем с конца:
<td align=right>Пароль:</td>
<td><input type=password name=pp size=25 value='' tabindex=5></td> 
видно что переменная которая содержит пароль называется pp.
Логин:<input name="uu" size="25" tabindex="4" type="text" value="" />
аналогично, переменная с логином называется uu.

<input type=hidden name=ses value=111111>
А в hiden спрятана переменная  ses=111111
<input type=hidden name=a value=98>
Аналогично спрятана в  hiden другая  переменная  a =98

С остальными переменными понятно, но что же означают ses и а ?
Формирование запроса
<form method=get action='/cgi-bin/stat.pl' onsubmit='pp.value=hex_md5(ses.value+" "+pp.value); return true'>

Для запроса используется метод GET, а формирование ссылки происходит с помощью некой функции hex_md5(), при чем как аргумент пересылается ему строка формата:
[ses] [pp]
То есть состоит из таинственной для нас переменной ses через пробел с паролем pp.
Что такое md5?
MD5 (англ. Message Digest 5) — 128-битный алгоритм хеширования, разработанный профессором Рональдом Л. Ривестом из Массачусетского технологического института (Massachusetts Institute of Technology, MIT) в 1991 году. Предназначен для создания «отпечатков» или «дайджестов» сообщений произвольной длины. Является улучшенной в плане безопасности версией MD4. Зная MD5-образ (называемый также MD5-хеш или MD5-дайджест), невозможно восстановить входное сообщение, так как одному MD5-образу могут соответствовать разные сообщения.
Проще говоря шифрует пароль, да так что в обратную сторону потчти невозможно расшифровать.
Механизм формирования ссылки более-менее понятен: через командную строку отправляются данные о логине пароле, переменная ses, переменная а.
Понаблюдав за переменными, можно сделать вывод:
ses — изменяющая свое значение переменная, правда не чаcто гдето 1-2 раза в сутки, используется для шифрования пароля.
a — статическая, не меняется, скорее всего отвечает за идентификацию необходимой формы.

Теперь самое время уточнить задачу:
  1. Получить код страници с формой для авторизации;
  2. Выделить значение переменной ses;
  3. Сформировать строку для зашифровки;
  4. Используя алгоритм md5 зашифровать строку;
  5. сформировать и выполнить запрос по ссылке.
Реализация
Вот что у мну получилось:

#!/usr/bin/env python
import re
import urllib
import hashlib
import logging
import sys

uu=11111 #user name
pp=1111  #password
a=98     #static variable

#intit dictionary of debug levels
LEVELS = {'-debug': logging.DEBUG,
          '-info': logging.INFO,
          '-warning': logging.WARNING,
          '-error': logging.ERROR,
          '-critical': logging.CRITICAL}
#Check for programmed arguments (arguments passed through command line)
if len(sys.argv) > 1:
    level_name = sys.argv[1]
    level = LEVELS.get(level_name, logging.NOTSET)
    logging.basicConfig(level=level)
#logging.basicConfig(level=logging.DEBUG)


# Get a file-like object for the Python Web site's home page.
f = urllib.urlopen(u"http://stat.pautina-nau.net/cgi-bin/stat.pl?a=101&a=99")
# Read from the object, storing the page's contents in 'html_page'.
html_page = f.read()
f.close()
logging.debug(html_page)
logging.debug("\n ***********************************************")

#find needed value from hidden form using regular expression
match = re.search( ur"name=ses[\s]+value=([0-9]{2,8})", html_page )
ses = match.group(1).encode( "cp1251" )
logging.debug("ses = "+ ses)

#encode password with md5 algorithm
pp_value = hashlib.new('md5')
pp_value.update(str(ses)+" "+str(pp))
pp = pp_value.hexdigest()
logging.debug(pp)

#form executable url
params = urllib.urlencode({'ses': ses, 'a': 98, 'pp': pp})
f = urllib.urlopen("http://stat.pautina-nau.net/cgi-bin/stat.pl?%s" % params)
f.read()
html_page_resp = f.read()
f.close()

Как по мну полезный пример, только не содержит функции обновления каждые 40 секунд. Позже разберусь с таймерами и уже в следующей статье дам более подробное описание кода скрипта.

Friday, February 19, 2010

Инженерная шутка


Бесцельно странствуя в просторах Интернета, наткнулся на интересную студенческую историю американского университета, которая представлена в оригинале далее:


The following is an actual question given on a University of Washington engineering mid-term. The answer was so "profound" that the Professor shared it with colleagues, and the sharing obviously hasn't ceased...

Bonus Question: Is Hell exothermic (gives off heat) or Endothermic (absorbs heat)?

Most of the students wrote Proofs of their beliefs using Boyle's Law, (gas cools off when it expands and heats when it is compressed) or some variant. One student, however, wrote the following:

"First, we need to know how the mass of Hell is changing in time. So we need to know the rate that souls are moving into Hell and the rate they are leaving. I think that we can safely assume that once a soul gets to Hell, it will not leave. Therefore, no souls are leaving. As for how many souls are entering Hell, let us look at the different religions that exist in the world today. Some of these religions state that if you are not a member of their religion, you will go to Hell. Since there are more than one of these religions and since people do not belong to more than one religion, we can project that all souls go to Hell. With birth and death rates as they are, we can expect the number of souls in Hell to increase exponentially.

Now, we look at the rate of change of the volume in Hell because Boyle's Law states that in order for the temperature and pressure in Hell to stay the same, the volume of Hell has to expand as souls are added. This gives two possibilities:

1. If Hell is expanding at a slower rate than the rate at which souls enter Hell, then the temperature and pressure in Hell will increase until all Hell breaks loose.

2. Of course, if Hell is expanding at a rate faster than the increase of souls in Hell, then the temperature and pressure will drop until Hell freezes over.

So which is it?

If we accept the postulate given to me by Teresa Banyan during my Freshman year, "...that it will be a cold day in Hell before I sleep with you.", and take into account the fact that I still have not succeeded in having sexual relations with her, then, #2 cannot be true, and thus I am sure that Hell is exothermic and will not freeze."

This student received the only A.

Friday, February 12, 2010

Python + Bluetooth, неужели просто?

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




1. Задача
Попробуем обнаружить, включенные по близости bluetooth устройства, определим их имя и адрес. Если повезет то может и удастся переслать файл.
2. Необходимо установить
Использовать будем библиотеку pybluez и lightblue.
[code lang=python]sudo apt-get install python-bluez, lightblue[/code]
3. Оброз наявной информации
1) Что такое bluetooth почитаем здесь:
http://en.wikipedia.org/wiki/Bluetooth
2)Очень неплохая книга, правда на ангилйском языке: Bluetooth Essentials for Programmers
http://www.btessentials.com/examples/examples.html
http://www.ebook3000.com/Bluetooth-Essentials-for-Programmers_4851.html
3)Описание библиотеки lightblue:
http://lightblue.sourceforge.net/
4. Реализация
Вот есть простой пример:

#!/usr/bin/env python
from bluetooth import *
target_name = "k750i";
target_address = None

nearby_devices = discover_devices()
for address in nearby_devices:
    if target_name == lookup_name( address ):
        target_address = address
        break
if target_address is not None:
    print "found target bluetooth device with address", target_address
else:
    print "could not find target bluetooth device nearby"
пере запуском необходимо отредактировать следующую строку:
target_name = "My Phone" 
My Phone — название Вашего телефона или bluetooth устройства. Перед запуском нужно конечно же что бы bluetooth на телефоне был включен и выставлена опция «видимый для всех»
Программа должна по идеи ответить:
found target bluetooth device with address 00:12:34:56:78:AB
00:12:34:56:78:AB - собственно адрес Вашего усройства.
Немного модифицируем скрипт:
#!/usr/bin/env python
from bluetooth import *
print 'start of search'
nearby_devices = discover_devices()
for address in nearby_devices:
    print 'name of device = ', lookup_name( address ),'address = ',address
print 'end'
Очевидно, что discover_devices() ищет все включенные по близости устройства и сохраняет их в словарь, а последующий цикл выводит имена и 48 битные адреса устройств.
Результат выполнения:
start of search
name of device = k750i address = 00:12:34:56:78:AB
name of device = nokia 6300 address = 00:12:34:56:78:AB
end
Так искать bluetooth устройства получилось. Правда практичной задачу особо не назовешь. В следующей заметке попробую написать о передачи файла с ноутбука на телефон с помощью библиотеки lightblue, так же надо бы разобраться с функцией иследования сервисов bluetooth устройства.

Thursday, February 11, 2010

Matlab формулы через LaTeX в MS Word.

Проблема

Очень часто приходится в лабораторных, домашних и курсовых работах портировать/набирать формулы, дабы показать цепочку размышлений, алгоритм или аналитический вывод. К тому же очень часто используется Matlab, для расчетов. Если задача решается символьно (symbolic computations) то по сути надо перенабивать формулы вывода Matlab с командного окна в Word или Open Office. Довольно нудная и неблагодарная работа.

Решение

Порившись немного в help, нашел все таки, что нужно. Есть такая функция latex(), которая представляет символьное выражение в LaTeX виде.  Да к стате, чтобы  переводить формулы из Matlab в MS Word, LaTex знать не обязательно.
Для примера возьмем простую программку:
%clear workspace and console output
clc
clear
%define of symbolic variables  
syms t beta_1 omega

%build symbolic expression 
%movement of angle  
alpha_2=atan(tan(t*omega)/cos(beta_1))
%differentiates movement of angle 2 times
ddalpha_2=diff(alpha_2,t,2)



Вывод в консоли будет следующим:
alpha_2 =
 
atan(tan(omega*t)/cos(beta_1))
 
 
ddalpha_2 =
 
(2*omega^2*tan(omega*t)*(tan(omega*t)^2 + 1))/(cos(beta_1)*(tan(omega*t)^2/cos(beta_1)^2 + 1)) - (2*omega^2*tan(omega*t)*(tan(omega*t)^2 + 1)^2)/(cos(beta_1)^3*(tan(omega*t)^2/cos(beta_1)^2 + 1)^2)


Не очень читабельно, не правда ли? Можно конечно использовать функцию pretty (), что сделает формулы наглядными, но в любом случае надо будет их вручную набирать.
Добавим в коде еще пару строк:

tex_out_alpha_2 = latex(alpha_2)
tex_out_ddalpha_2 = latex(ddalpha_2)

Эти команды просто преобразуют коды Matlab в LaTeX. В командном окне получим результаты:
tex_out_alpha_2 =

\arctan\!\left(\frac{\tan\!\left(\mathrm{omega}\, t\right)}{\cos\!\left(\mathrm{beta}_{1}\right)}\right)


tex_out_ddalpha_2 =

\frac{2\, {\mathrm{omega}}^2\, \tan\!\left(\mathrm{omega}\, t\right)\, \left({\tan\!\left(\mathrm{omega}\, t\right)}^2 + 1\right)}{\cos\!\left(\mathrm{beta}_{1}\right)\, \left(\frac{{\tan\!\left(\mathrm{omega}\, t\right)}^2}{{\cos\!\left(\mathrm{beta}_{1}\right)}^2} + 1\right)} - \frac{2\, {\mathrm{omega}}^2\, \tan\!\left(\mathrm{omega}\, t\right)\, {\left({\tan\!\left(\mathrm{omega}\, t\right)}^2 + 1\right)}^2}{{\cos\!\left(\mathrm{beta}_{1}\right)}^3\, {\left(\frac{{\tan\!\left(\mathrm{omega}\, t\right)}^2}{{\cos\!\left(\mathrm{beta}_{1}\right)}^2} + 1\right)}^2}

Бред... Он нам поможет!!!

Что бы корректно воспроизвести формулы, необходимо установить надстройку для MS Word, которая называется MathType. В моем случае была использована 6 я версия. Устанавливаем прогу, появляется новая вкладка (Office 2007) на панели. Дальше нужно проделать следующие действия (в картинках, без комментариев):
Step 1
Step 2
 
Step 3
  

Step 4
  

Step 5
 

Все сконфигурировано, теперь просто вставим LaTeX (тот бредовый набор символов ) текст в редактор  формул, результат будет слудующим:
 


Неплохо, правда? Первую формулу можно было конечно набрать, но вторую? (Мне было бы лень)
Нужно заметить, что в LaTeX индекс обозначается через нижние подчеркивание, k_1 = k1. То есть обозначив символьную переменную в таком виде, мы определяем ее индекс. Важно, то что если переменная будет задана в виде k_22 то индексом будет считаться только первый символ, результат будет k12. (в LaTeX если символов в индексе больше чем один, их нужно заключить в фигурные скобки k_{22} ).Важно это помнить, да бы не запутаться потом.

Теперь попробуем заменить названия переменных на грецкие буквы:
Немного модифицируем нашу программу:

clc
clear
syms t beta_1 omega
alpha_2=atan(tan(t*omega)/cos(beta_1))
ddalpha_2=diff(alpha_2,t,2)
tex_out_alpha_2 = latex(alpha_2)
tex_out_ddalpha_2 = latex(ddalpha_2)

%find 'beta'  and replace on  '\\beta'
str_find='beta'
str_replace = '\\beta'
str_out = regexprep(tex_out_alpha_2, str_find, str_replace)

%find 'omega'  and replace on  '\\omega' 
str_find ='omega'
str_replace = '\\omega'
str_out = regexprep(str_out, str_find, str_replace)


Добавленные команды 'beta' на '\\beta' (для LaTeX нужно только \beta, но для того чтобы Matlab не запутался, \ обозначают как \\).
\beta и \omega -нарисует соответственно грецкую бету и омегу.



Так лучше?Теперь попробуем вставить LaTeX код в Kile. Минимальный документ с формулой будет иметь вид:


\documentclass[a4paper,10pt]{article}
\usepackage[utf8x]{inputenc}

%opening
\title{}
\author{}

\begin{document}

\maketitle

\begin{abstract}

\end{abstract}

\[
\frac{2\, {\mathrm{\omega}}^2\, \tan\!\left(\mathrm{\omega}\, t\right)\, \left({\tan\!\left(\mathrm{\omega}\, t\right)}^2 + 1\right)}{\cos\!\left(\mathrm{\beta}_{1}\right)\, \left(\frac{{\tan\!\left(\mathrm{\omega}\, t\right)}^2}{{\cos\!\left(\mathrm{\beta}_{1}\right)}^2} + 1\right)} - \frac{2\, {\mathrm{\omega}}^2\, \tan\!\left(\mathrm{\omega}\, t\right)\, {\left({\tan\!\left(\mathrm{\omega}\, t\right)}^2 + 1\right)}^2}{{\cos\!\left(\mathrm{\beta}_{1}\right)}^3\, {\left(\frac{{\tan\!\left(\mathrm{\omega}\, t\right)}^2}{{\cos\!\left(\mathrm{\beta}_{1}\right)}^2} + 1\right)}^2}
\]
\end{document} 



Нужно заметить, что в LaTeX редакторах нужно не просто вставить формулу из Matlab, но заключить ее в  "\[" и  "\[" (без кавычек):

\[
\arctan\!\left(\frac{\tan\!\left(\mathrm{\omega}\, t\right)}{\cos\!\left(\mathrm{\beta}_{1}\right)}\right)
\] 

Думаю идея понятна))), надеюсь поможет Вам с экономить время и избавиться от рутинной работы. Когда разберусь с регулярными выражениями, постараюсь решить проблему с индексами да и более красиво реализовать замену строк.
 Полезные ссылки:
http://www.mathworks.com/access/helpdesk/help/toolbox/symbolic/latex.html
http://www.math.harvard.edu/texman/node21.html