<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ZetBlog&#187; Программирование</title>
	<atom:link href="http://zetblog.ru/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://zetblog.ru</link>
	<description>Зеты говорят. Блог о программировании, администрировании и безопасности.</description>
	<lastBuildDate>Sat, 29 Oct 2011 18:59:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Delphi: Пишем шаблон клиент-серверного приложения.</title>
		<link>http://zetblog.ru/programming/201004/delphi-%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd/</link>
		<comments>http://zetblog.ru/programming/201004/delphi-%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 07:47:37 +0000</pubDate>
		<dc:creator>C0ffe1n</dc:creator>
				<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[сетевое]]></category>
		<category><![CDATA[ClientSocket]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[ServerSocket]]></category>
		<category><![CDATA[сеть]]></category>
		<category><![CDATA[файлы]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=913</guid>
		<description><![CDATA[Продолжая тему разработки собственной утилиты администрирования, в данной статье я рассмотрю типовой шаблон программы клиент-сервер, на базе которой можно разрабатывать собственные клиент-серверные приложения. Данный типовой шаблон для простоты понимания и удобства применения будет рассмотрен на примере компонентов ClientSocket и ServerSocket. Примечание Для тех, кто не в курсе, что значит клиент-серверное приложение, поясню: это комплекс программ [...]]]></description>
			<content:encoded><![CDATA[<p>Продолжая тему разработки собственной утилиты администрирования, в данной статье я рассмотрю типовой шаблон программы клиент-сервер, на базе которой можно разрабатывать собственные клиент-серверные приложения. Данный типовой шаблон для простоты понимания и удобства применения будет рассмотрен на примере компонентов <strong>ClientSocket</strong> и <strong>ServerSocket</strong>.<br />
<span id="more-913"></span><strong></strong></p>
<p><strong>Примечание</strong></p>
<div class="codesnip-container" >Для тех, кто не в курсе, что значит клиент-серверное приложение, поясню: это комплекс программ (модулей) состоящий из двух частей &#8212; клиентской и серверной. Серверная часть является &#171;главной&#187;- так называемый командный пункт, на который возложена задача поддержания связи со всеми клиентами и раздача команд управления, соответствующих их функционалу (управление клиентами). Клиентская же часть является второстепенной, но не менее важной, так как является важным и связующим элементом, позволяющим выполнять удаленные команды (функции) на компьютере, на котором установлен.</div>
<div class="codesnip-container" >Компоненты <strong>ClientSocket</strong> и <strong>ServerSocket</strong>, которые мы будем использовать, находятся на вкладке <strong>Internet</strong>. Если на этой вкладке у Вас нет этих компонентов (а по умолчанию при установке <strong>Delphi7</strong> они не ставятся), необходимо установить их самостоятельно (пакет <strong>dclsocketsXX.bpl</strong>). Данный пакет можно найти на установочном диске<strong> Delphi7</strong> (или в папке<span style="text-decoration: underline;"> C:\Temp</span>, куда распаковывается дистрибутив перед установкой &#8212; <span style="text-decoration: underline;">C:\Temp\delphi7\install\program files\borland\delphi7\bin\</span>) или можете его скачать <a href="/forum/downloadf/components/dclsockets70.rar">отсюда</a>. Чтобы установить данный пакет, запустите <strong>Delphi7</strong>. Зайдите в меню <span style="text-decoration: underline;">Component-&gt;Install Packages</span>. В появившемся окне нажмите кнопку <strong>&#171;Add&#187;</strong> и укажите место, где расположен пакет <strong>dclsocketsXX.bpl</strong>. После этого жмите<strong> ОК</strong>. Компонент на месте. ;)</div>
<p>Надеюсь все объяснил доступно =). А теперь приступим к делу и начнем мы с серверной части. Для этого создадим проект и скинем на форму компонент <strong>ServerSocket</strong>. В настройках компонента <strong>ServerSocket</strong> укажем следующее:</p>
<div class="codesnip-container" >Active = false<br />
Name = ss<br />
Port = 4321<br />
ServerType = stNonBlocking</div>
<p>А также для удобства скинем компонент <strong>Memo</strong>, в который будем выводить всякую инфу. Дадим имя компоненту <strong>log</strong>.</p>
<p>Далее, для компонента <strong>ServerSocket</strong> определяем метод <strong>onClientConnect</strong>, чтобы определять момент подключения клиентов. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.ssClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.Lines.Add(formattedDateTime+': Есть коннект c '+Socket.RemoteAddress);
  { далее вы можете вставить свой код }
end;</pre>
<p>А теперь определим метод <strong>onClientRead</strong>, в котором будем обрабатывать получаемые сообщения от клиентов:</p>
<pre class=".brush: pascal">procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  s:string;
begin
  s:=Socket.ReceiveText;
  log.Lines.Add(s);
end;</pre>
<p>Определим метод<strong> onClientDisconnect</strong>, чтобы фиксировать факт отключения клиента:</p>
<pre class=".brush: pascal">procedure TForm1.ssClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.Lines.Add(formattedDateTime+': Клиент '+socket.RemoteAddress+' отключился.');
end;</pre>
<p>На этом с серверной частью покончено =).</p>
<p>Приступим к клиентской части. Для этого создадим новый проект, скинем на форму компонент <strong>ClientSocket</strong> и таймер. В настройках компонента укажем следующее:</p>
<div class="codesnip-container" >Active = false<br />
Name = сs<br />
Port = 4321<br />
ClientType = ctNonBlocking<br />
Address = 127.0.0.1</div>
<p>Для простоты пояснения я в <strong>Address</strong> указал <strong>&#171;петлю&#187;</strong>. Но для гибкости приложения рекомендую это поле обрабатывать программно, во время <strong>CreateForm</strong> при обработке конфигурационного файла, в котором можно указывать нужный <strong>IP-адрес сервера</strong>.</p>
<p>Здесь также для удобства скинем на форму компонент <strong>Memo</strong>, в который будем выводить техническую инфу. Имя дадим соответствующее<strong> log</strong>.</p>
<p>Для компонента <strong>ClientSocket</strong> определяем метод <strong>onError</strong> для того, чтобы обрабатывать исключения, возникшие в момент подключения клиента к серверу. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.csError(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
 if ErrorEvent= eeConnect  then
  begin
    cs.Active:=false;
      {добавить запись в журнал};
    mydate:=Now;
    DateTimeToString(formattedDateTime, 'c', myDate);
    log.lines.Add(formattedDateTime+': Невозможно установить соединение с сервером - '+cs.Address);
  end;
  ErrorCode:=0;
  { далее вы можете вставить свой код }
end;</pre>
<p>Теперь определим метод <strong>onConnect</strong>. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.csConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.lines.Add(formattedDateTime+': Соединение с сервером - '+socket.RemoteAddress+' установлено.');
end;</pre>
<p>И чтобы фиксировать момент потери связи с сервером, определим метод <strong>onDisconnect</strong>:</p>
<pre class=".brush: pascal">procedure TForm1.csDisconnect(Sender: TObject; Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now; //получим текущее время
  DateTimeToString(formattedDateTime, 'c', myDate); //преобразуем в строку
  log.Lines.Add(formattedDateTime+': Соединение с сервером '+socket.RemoteAddress+' потеряно.');
end;</pre>
<p>Таймер настроим так:</p>
<div class="codesnip-container" >Enabled = true<br />
Name = te<br />
Interval = 5000</div>
<p>И определяем метод <strong>onTimer</strong>. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.Timer1Timer(Sender: TObject);
begin
if not cs.Active then
  begin
    cs.Active:=true;
  end;
  cs.Socket.SendText('ping client');
end;</pre>
<p>Данный код проверяет наличие соединения с сервером и в случае его отсутствия пытается его установить.<br />
И каждые 5 секунд отправляет серверу сообщение <strong>&#171;ping client&#187;</strong>.</p>
<p>Вот примерно так выглядит типовой шаблон приложения <strong>&#171;клиент-сервер&#187;</strong>.</p>
<p><strong>Примечание</strong></p>
<div class="codesnip-container" >Хотел бы обратить внимание на обработчик <strong>onError</strong> тех, кто ранее не знал как избавиться от злосчастного сообщения &#8212; <strong>&#171;Asynchronous socket error 10061&#8243;</strong>, возникающее при попытке осуществления подключения к серверу, который недоступен.</div>
<p>Рабочий пример можно скачать <a title="Рабочий пример" href="/forum/downloadf/simples/client-server.rar">отсюда</a>.</p>
<p>Если есть кому что добавить или задать вопрос по теме &#8212; прошу отписываться в комментах ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201004/delphi-%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Python: Маленькая хитрость. if-else vs and-or.</title>
		<link>http://zetblog.ru/programming/201003/python-if-else-vs-and-or/</link>
		<comments>http://zetblog.ru/programming/201003/python-if-else-vs-and-or/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 19:30:57 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[общие вопросы]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=980</guid>
		<description><![CDATA[На этот раз будет мини-заметка, уж слишком мне понравился трюк, о котором пойдёт речь дальше :). Наверное любому программисту приходится часто писать конструкции такого вида: if a == b: c = d else: c = e Как-то разбирая исходники какого-то проекта наткнулся на весьма компактную замену. Вот для сравнения два аналогичных блока кода с использованием [...]]]></description>
			<content:encoded><![CDATA[<p>На этот раз будет мини-заметка, уж слишком мне понравился трюк, о котором пойдёт речь дальше :). </p>
<p>Наверное любому программисту приходится часто писать конструкции такого вида:</p>
<pre class=".brush: python">if a == b:
    c = d
else:
    c = e</pre>
<p>Как-то разбирая исходники какого-то проекта наткнулся на весьма компактную замену. Вот для сравнения два аналогичных блока кода с использованием логических операций python&#8217;а и с использованием конструкции if-else:</p>
<pre class=".brush: python"># if-else:
if random.random() > 0.5:
    a = 1
else:
    a = 0

# and-or style:
a = random.random() > 0.5 and 1 or 0</pre>
<p>На мой взгляд выглядит гораздо лучше и компактнее (да-да, if-else можно записать в 2 строчки вместо 4, но мне так не нравится ^__^) . Другое дело, что некоторым это может показаться противоречиво с некоторыми пунктами дзена python&#8217;а (import this), но это спорно :). В общем использую там, где считаю нужным.</p>
<p>Кстати, если кого-то интересует производительность, то она примерно одинакова, далее выложу тесты и объяснение логики для тех, кому интересно.<br />
<span id="more-980"></span></p>
<pre class=".brush: python">>>> import timeit
>>> t1 = timeit.Timer('if random.random()>0.5:a=1\nelse:a =0', 'from __main__ import a\nimport random')
>>> t2 = timeit.Timer('a=random.random()>0.5 and 1 or 0', 'from __main__ import a\nimport random')
>>> t1.repeat()
[0.21074632467116317, 0.2097615509806019, 0.20978293771349854]
>>> t2.repeat()
[0.21944338095772764, 0.21785226684687586, 0.21940797240040411]
</pre>
<p>Тесты привёл, теперь объяснение.</p>
<p>Дело в том, что логические операции <strong>and</strong> и <strong>or</strong> в python&#8217;е возвращают один из операндов. Операция and возвращает первый операнд, если он приводится к логическому типу False, иначе &#8212; второй. Операция or наоборот, возвращает 1й операнд, если он приводится к типу True, иначе &#8212; второй. Всё это связано с &#171;ленивостью&#187; (lazy) операций, вычисляется столько аргументов, сколько надо для того, чтобы однозначно определить результат (например, 1 or x всегда даёт True, поэтому x не вычисляется).</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201003/python-if-else-vs-and-or/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>WordPress: Модернизация плагина statpress.</title>
		<link>http://zetblog.ru/programming/201002/wordpress-statpress-russian-optimization/</link>
		<comments>http://zetblog.ru/programming/201002/wordpress-statpress-russian-optimization/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 09:59:08 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[StatPress]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=948</guid>
		<description><![CDATA[Статистика &#8212; вещь не только интересная, но иногда и полезная :). WordPress &#8212; один из популярнейших движков php для блогов, для него существует огромное количество плагинов, в том числе и плагины для просмотра статистики по посещаемости. Один из таких плагинов &#8212; statpress. Но есть в нём некоторые недостатки, автор плагина добавил распознавание некоторых русских поисковых [...]]]></description>
			<content:encoded><![CDATA[<p>Статистика &#8212; вещь не только интересная, но иногда и полезная :). WordPress  &#8212; один из популярнейших движков php для блогов, для него существует огромное количество плагинов, в том числе и плагины для просмотра статистики по посещаемости. Один из таких плагинов &#8212; statpress. Но есть в нём некоторые недостатки, автор плагина добавил распознавание некоторых русских поисковых движков, но так же некоторые упустил из виду. Хотя даже тот же Яндекс обрабатывается не очень хорошо, не учитываются переходы с yandex.ua, yandex.kz и т.п. Но opensource тем и хорош, что всегда можно поправить исходники, если что-то тебя не устраивает :). Далее пойдёт речь об оптимизации плагина statpress под Российские поисковики.<br />
<span id="more-948"></span></p>
<p>В общем надоело мне то, что не учитывается часть поисковиков, надоело смотреть на ссылки с этих поисковиков в &#171;последних ссылающихся ресурсах&#187;, как оказалось, подправить это доваольно легко. С недельку ещё последил для отлова поисковых движков, и вот примерный список улучшений:</p>
<ul>
<li><strong>Yandex</strong> &#8212; улучшено поддержка (теперь распознаётся yandex.kz, yandex.ua. В общем то теперь маска для яндекса выглядит так: yandex.*, в связи с этим так же распознаются переходы вида yandex.ru/schoolsearch?text=* и т.п.);</li>
<li><strong>Nigma</strong> &#8212; добавлена поддержка поисковика nigma.ru</li>
<li><strong>Go Mail.ru</strong> &#8212; добавлена поддержка поисковика Go от Mail.Ru</li>
<li><strong>QIP</strong> &#8212; добавлена поддержка поисковика от QIP&#8217;а</li>
<li><strong>bing.</strong> &#8212; добавлен поисковик bing.com</li>
<li><strong>Rambler</strong> &#8212; улучшена поддержка поисковика от Рамблера</li>
</ul>
<p>Так же из &#171;ссылающихся ресурсов&#187; убараны ссылки вида &#171;*google.*&#187;, если это нововведение вам не нужно, не заменяйте в своём плагине файл statpress.php. У меня почему-то появилась куча ссылок на меня с гугла, по которым находится что-то вроде &#171;ресурс zetblog.ru пытается перенаправить вас&#187;. В случае обновления statpress.php такая проблема исчезнет, но могут так же пропасть и нужные ссылки с google (если они есть вообще).</p>
<p>После обновления файлов плагина необходимо обновить БД статистики (достаточно долгий процесс&#8230; особенно если база большая), делается это через админку wordpress путём одинарного клика по кнопке StatPressUpdate ^__^.</p>
<p>Если что-то какие-то поисковики упустил &#8212; пишите в комменты, обновлю. Ну, либо сам, если узнаю об этом :). Надеюсь, кому-то это поможет.</p>
<p>Ссылки на скачивание всего этого:<br />
<a href="http://depositfiles.com/files/3lujgxn3d">http://depositfiles.com/files/3lujgxn3d</a> &#8212; плагин полностью на депозите.<br />
Позже (по первой просьбе или как дойдут руки)) добавлю ссылку на скачивание с этого ресурса.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201002/wordpress-statpress-russian-optimization/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Hibernate: Удаление объектов из БД.</title>
		<link>http://zetblog.ru/programming/201002/hibernate-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8%d0%b7-%d0%b1%d0%b4/</link>
		<comments>http://zetblog.ru/programming/201002/hibernate-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8%d0%b7-%d0%b1%d0%b4/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 10:35:29 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Jython]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=921</guid>
		<description><![CDATA[По работе пришлось изучать работу Java&#8217;вского ORM&#8217;а, пока что знаком только бегло, но некоторые полезные штуки для новичка решил записать. Может кому пригодится, может нет, но хотя бы самому гуглить придётся меньше =). Кстати, примеры будут не на Java, а на Jython&#8217;е, т.к. с первым я тоже не очень знаком :). Итак, опустим настройку и [...]]]></description>
			<content:encoded><![CDATA[<p>По работе пришлось изучать работу Java&#8217;вского ORM&#8217;а, пока что знаком только бегло, но некоторые полезные штуки для новичка решил записать. Может кому пригодится, может нет, но хотя бы самому гуглить придётся меньше =). Кстати, примеры будут не на Java, а на Jython&#8217;е, т.к. с первым я тоже не очень знаком :).</p>
<p>Итак, опустим настройку и подключение Hibernate, предположим, что вы это уже сделали :). Быть может, напишу об этом позже. Требуется удалить из таблицы player (которая маппится с классом Player, естественно&#8230; или наоборот :) ) некоторые записи. Если мы знаем id игрока, тогда всё элементарно (как и в других случаях)):</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;">player = session.<span class="me1">load</span><span class="br0">&#40;</span>Player, player_id<span class="br0">&#41;</span><br />
session.<span class="me1">delete</span><span class="br0">&#40;</span>player<span class="br0">&#41;</span></div>
</div>
<p>Теперь рассмотрим случай, когда надо удалить много записей.<span id="more-921"></span></p>
<p>В ORM&#8217;е Hibernate несколько способов провернуть это. 1й &#8212; очевидный, с помощью createQuery выбрать все нужные записи HQL&#8217;ом и в цикле удалять по одной:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;">players_list = session.<span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st0">&quot;FROM Player WHERE name = :name&quot;</span><span class="br0">&#41;</span>\
&nbsp; &nbsp; .<span class="me1">setParameter</span><span class="br0">&#40;</span><span class="st0">&quot;name&quot;</span>, <span class="st0">&quot;Василий&quot;</span><span class="br0">&#41;</span>\
&nbsp; &nbsp; .<span class="kw2">list</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="kw1">for</span> player <span class="kw1">in</span> players_list:
&nbsp; &nbsp; session.<span class="me1">delete</span><span class="br0">&#40;</span>player<span class="br0">&#41;</span></div>
</div>
</pre>
<p>Но это влечёт накладные расходы на получение всех нужных объектов, а затем удаление по одному, в таком случае мы выполним столько sql-запросов, сколько объектов загрузили, что может ухудшить производительность приложения. Для этого есть другой способ. Вот в общем то и он:</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;">session.<span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st0">&quot;DELETE Player WHERE name = :name&quot;</span><span class="br0">&#41;</span>\<br />
&nbsp; &nbsp; .<span class="me1">setParameter</span><span class="br0">&#40;</span><span class="st0">&quot;name&quot;</span>, <span class="st0">&quot;Василий&quot;</span><span class="br0">&#41;</span>\<br />
&nbsp; &nbsp; .<span class="me1">executeUpdate</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
<p>Вот таким способом можно избавиться от всех неугодных нам Василиев ;). Так же есть возможность воспользоваться сырым sql с помощью Session.createSQLQuery().</p>
<p>Ссылки:<br />
<a href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/batch.html#batch-direct">Документация по Hibernate</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201002/hibernate-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8%d0%b7-%d0%b1%d0%b4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python: Реализация простого web-сервера.</title>
		<link>http://zetblog.ru/programming/200911/python-simple-web-server/</link>
		<comments>http://zetblog.ru/programming/200911/python-simple-web-server/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 16:26:00 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[BaseHTTPServer]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=757</guid>
		<description><![CDATA[Не для собственных нужд, но как-то понадобилось написать простой web-сервер для обработки на нём загруженных данных. В общем-то должен был получиться простой вёб-интерфейс к программе. Он и получился, местами даже слишком простой. В общем суть такова &#8212; необходимо получить от пользователя экзешник, на сервере его обработать нужными программами и выдать результат, т.е. обработанный файл для [...]]]></description>
			<content:encoded><![CDATA[<p>Не для собственных нужд, но как-то понадобилось написать простой web-сервер для обработки на нём загруженных данных. В общем-то должен был получиться простой вёб-интерфейс к программе. Он и получился, местами даже слишком простой. В общем суть такова &#8212; необходимо получить от пользователя экзешник, на сервере его обработать нужными программами и выдать результат, т.е. обработанный файл для скачивания. Можно было бы написать скрипт на php, что было бы проще, но тогда необходимо с собой таскать какой-нибудь вёб-сервер (apache, denwer и т.п.). На питоне можно его реализовать достаточно просто в самом скрипте используя стандартные заготовки и библиотеки, такие как BaseHTTPServer. Ниже следует листинг с краткими комментариями.<br />
<span id="more-757"></span></p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1"># -*- coding: utf-8 -*-</span>

<span class="kw1">import</span> <span class="kw3">cgi</span>
<span class="kw1">from</span> <span class="kw3">os</span> <span class="kw1">import</span> curdir, sep
<span class="kw1">from</span> <span class="kw3">BaseHTTPServer</span> <span class="kw1">import</span> BaseHTTPRequestHandler, HTTPServer
<span class="kw1">import</span> <span class="kw3">subprocess</span>

<span class="kw1">class</span> MyHandler<span class="br0">&#40;</span>BaseHTTPRequestHandler<span class="br0">&#41;</span>:
&nbsp; &nbsp; <span class="kw1">def</span> do_GET<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">path</span> <span class="sy0">!</span>= <span class="st0">&quot;/output.exe&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>curdir+sep+<span class="st0">&quot;upload.html&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span>200<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_header</span><span class="br0">&#40;</span><span class="st0">&quot;Content-type&quot;</span>, <span class="st0">&quot;text/html&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span>f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span>200<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_header</span><span class="br0">&#40;</span><span class="st0">&quot;Content-type&quot;</span>, <span class="st0">&quot;application/octet-stream&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="kw2">open</span><span class="br0">&#40;</span>curdir+sep+<span class="st0">&quot;output.exe&quot;</span>, <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">IOError</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_error</span><span class="br0">&#40;</span><span class="nu0">404</span>,<span class="st0">&quot;File Not Found: %s&quot;</span> <span class="sy0">%</span> <span class="kw2">self</span>.<span class="me1">path</span><span class="br0">&#41;</span>

&nbsp; &nbsp; <span class="kw1">def</span> do_POST<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctype, pdict = <span class="kw3">cgi</span>.<span class="me1">parse_header</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">headers</span>.<span class="me1">getheader</span><span class="br0">&#40;</span><span class="st0">&quot;content-type&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> ctype == <span class="st0">&quot;multipart/form-data&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; query = <span class="kw3">cgi</span>.<span class="me1">parse_multipart</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">rfile</span>, pdict<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span>200<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upfile = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;file&quot;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>curdir+sep+<span class="st0">&quot;output.exe&quot;</span>, <span class="st0">&quot;wb&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span>upfile<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params = <span class="st0">&quot; np output.exe&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;encryption&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;aes&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 1&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;rc5&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 2&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;xor&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 3&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 0&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;hw_bind&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;yes&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;hw_bind_serial&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">assert</span> <span class="kw2">len</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> == <span class="nu0">8</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sn &quot;</span> + p<span class="br0">&#91;</span>0<span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sn 0&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;passwd&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">assert</span> <span class="kw2">len</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span>gt<span class="sy0">;</span> <span class="nu0">0</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; pass &quot;</span> + p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;pack&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;yes&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; pack 1&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; pack 0&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pipe = <span class="kw3">subprocess</span>.<span class="me1">Popen</span><span class="br0">&#40;</span><span class="st0">&quot;processor.exe &quot;</span>+params, shell=<span class="kw2">True</span>, stdin=<span class="kw3">subprocess</span>.<span class="me1">PIPE</span>, stdout=<span class="kw3">subprocess</span>.<span class="me1">PIPE</span>, stderr=<span class="kw3">subprocess</span>.<span class="me1">PIPE</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pipe.<span class="me1">stdin</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pipe.<span class="me1">wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'&lt;a href=&quot;/output.exe&quot;&gt;Download results&lt;/a&gt;.'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> :
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">pass</span>

<span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:
&nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; server = HTTPServer<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;</span>, 8080<span class="br0">&#41;</span>, MyHandler<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;started httpserver...&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; server.<span class="me1">serve_forever</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;^C received, shutting down server&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; server.<span class="kw3">socket</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
</pre>
<p>Итак, для начала импортируем из библиотеки BaseHTTPServer два класса: HTTPserver — собственно, сам вёб-сервер и BaseHTTPRequestHandler — класс, который служит для обработки запросов от пользователей.</p>
<p>Объявляем свой класс MyHandler, который наследуется от BaseHTTPRequestHandler. И перегружаем в нём два метода — do_GET и do_POST для обработки данных, переданных методом GET и POST, соответственно.</p>
<p>В первом обработчике проверяем запрос от пользователя (содержится в  self.path), если запрашиваемый документ не является /output.exe, то выдаём форму для загрузки файла, иначе — считываем и выдаём output.exe. Так же, перед этим, посылается ответ от сервера с кодом 200, что соответствует успешной обработке запроса от клиента и передаём заголовок, в котором указан тип содержимого (text/html для html-код или application/octet-stream для бинарного файла).</p>
<p>В обработке POST-запроса проверяем какие данные были переданы. Сначала получаем файл и записываем его под именем output.exe. Далее формируем строку параметров на основе переданных от пользователя данных, запускаем хранящуюся на сервере программу для обработки полученных файлов, ждём пока она завершится и выдаём ссылку на скачивание результата.</p>
<p>Далее, в самой программе создаём вёб-сервер, указав при этом порт, на котором он будет работать (в примере это 8080) и класс, который необходимо использовать для обработки запросов от пользователей.</p>
<p>Недостаток заключается в том, что данная реализация не сможет обработать одновременную загрузку файлов от разных пользователей, т.к. в лучшем случае просто один из запросов затрёт файл output.exe, полученный в другом запросе. Но такая задача не стояла. На мой взгляд хороший пример для демонстрации возможностей python&#8217;а.</p>
<p>Так же код html-файла upload.html, который должен располагаться в той же директории, что и сервер:</p>
<pre>
<div class="codesnip-container" >
<div class="html4strict codesnip" style="font-family:monospace;"><span class="sc2">&lt;<a href="http://december.com/html/4/element/form.html"><span class="kw2">form</span></a> <span class="kw3">action</span><span class="sy0">=</span><span class="st0">&quot;/&quot;</span> <span class="kw3">enctype</span><span class="sy0">=</span><span class="st0">&quot;multipart/form-data&quot;</span> <span class="kw3">method</span><span class="sy0">=</span><span class="st0">&quot;post&quot;</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/table.html"><span class="kw2">table</span></a> <span class="kw3">border</span><span class="sy0">=</span><span class="st0">&quot;1&quot;</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tbody.html"><span class="kw2">tbody</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Encryption:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">checked</span><span class="sy0">=</span><span class="st0">&quot;checked&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;none&quot;</span> <span class="sy0">/</span>&gt;</span>None
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;aes&quot;</span> <span class="sy0">/</span>&gt;</span>AES
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;rc5&quot;</span> <span class="sy0">/</span>&gt;</span>RC5
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;xor&quot;</span> <span class="sy0">/</span>&gt;</span>XOR<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Hardware binding:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">checked</span><span class="sy0">=</span><span class="st0">&quot;checked&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;hw_bind&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;no&quot;</span> <span class="sy0">/</span>&gt;</span>No
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;hw_bind&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;yes&quot;</span> <span class="sy0">/</span>&gt;</span>Yes
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;hw_bind_serial&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;media serial number&quot;</span> <span class="sy0">/</span>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Password:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;passwd&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;password&quot;</span> <span class="sy0">/</span>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Pack:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">checked</span><span class="sy0">=</span><span class="st0">&quot;checked&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;pack&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;no&quot;</span> <span class="sy0">/</span>&gt;</span>No
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;pack&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;yes&quot;</span> <span class="sy0">/</span>&gt;</span>Yes<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a> <span class="kw3">colspan</span><span class="sy0">=</span><span class="st0">&quot;2&quot;</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;file&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;file&quot;</span> <span class="sy0">/</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;submit&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;Отправить&quot;</span> <span class="sy0">/</span>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tbody.html"><span class="kw2">tbody</span></a>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/table.html"><span class="kw2">table</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/form.html"><span class="kw2">form</span></a>&gt;</span></div>
</div>
</pre>
<p>Ссылки к статье:<br />
<a href="http://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP"><br />
http://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP</a> &#8212; Список кодов состояния HTTP.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200911/python-simple-web-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: Проблема с подвисанием GUI на TkInter.</title>
		<link>http://zetblog.ru/programming/200910/python-tkinter-antifreeze/</link>
		<comments>http://zetblog.ru/programming/200910/python-tkinter-antifreeze/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 18:57:03 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[общие вопросы]]></category>
		<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[TkInter]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=731</guid>
		<description><![CDATA[Встала задача написания небольшой графической оболочки для программы с минимальным интерфейсом (одна кнопка и одно поле вывода). Много нам не надо, поэтому решил обойтись идущей вместе с python&#8217;ом в поставке библиотекой TkInter. И тут столкнулся с небольшой проблемой &#8212; при нажатии кнопки запускаются довольно долгие и объёмные вычисления, из-за которых виснет весь интерфейс программы. Решений [...]]]></description>
			<content:encoded><![CDATA[<p>Встала задача написания небольшой графической оболочки для программы с минимальным интерфейсом (одна кнопка и одно поле вывода). Много нам не надо, поэтому решил обойтись идущей вместе с python&#8217;ом в поставке библиотекой TkInter. И тут столкнулся с небольшой проблемой &#8212; при нажатии кнопки запускаются довольно долгие и объёмные вычисления, из-за которых виснет весь интерфейс программы.<br />
<span id="more-731"></span></p>
<p>Решений у этого вопроса несколько.<br />
1 &#8212; Запускать эти вычисления в отдельном потоке, что меня вполне устроило:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1"># -*- coding: utf-8 -*-</span>
<span class="kw1">from</span> <span class="kw3">Tkinter</span> <span class="kw1">import</span> <span class="sy0">*</span>
<span class="kw1">import</span> <span class="kw3">threading</span>, <span class="kw3">time</span>

<span class="kw1">class</span> AppGUI:
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">tk</span> = Tk<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frame = Frame<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">tk</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frame.<span class="me1">pack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Button<span class="br0">&#40;</span>frame, text=<span class="st0">&quot;Compute&quot;</span>, command=<span class="kw2">self</span>.<span class="me1">computeWithGUIAntifreeze</span><span class="br0">&#41;</span>.<span class="me1">pack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> run<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">tk</span>.<span class="me1">mainloop</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; <span class="kw1">def</span> computeWithGUIAntifreeze<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;&quot; Метод-прокладка для запуска в новом потоке вычислений &quot;&quot;&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">threading</span>.<span class="me1">Thread</span><span class="br0">&#40;</span>target=<span class="kw2">self</span>.<span class="me1">compute</span><span class="br0">&#41;</span>.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; <span class="kw1">def</span> compute<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;&quot;&quot; Тут как раз и происходят длительные вычисления &quot;&quot;&quot;</span><span class="st0">&quot;
&nbsp; &nbsp; &nbsp; &nbsp; time.sleep(15)

gui = AppGUI()
gui.run()</span></div>
</div>
</pre>
<p>2 &#8212; Использовать время от времени методы:</p>
<ul>
<li><strong>Tk.update()</strong>;</li>
<li><strong>Tk.update_idletasks()</strong> &#8212; только обновляет окна, но не вызывает обработку событий, сгенерированных пользователем, в отличие от Tk.update();</li>
</ul>
<p>Использовать эти методы стоит с осторожностью, дабы не возникло неприятных ситуаций (подробнее в документации). Таково предостережение официальной документации.</p>
<p>Ссылки к посту:<br />
<a href="http://www.tcl.tk/man/tcl8.5/TclCmd/update.htm">http://www.tcl.tk/man/tcl8.5/TclCmd/update.htm</a> &#8212; официальная документация по Tcl/Tk.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200910/python-tkinter-antifreeze/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: генератор списка паролей для перебора (brute-force).</title>
		<link>http://zetblog.ru/programming/200910/python-passwords-list-for-bruteforce/</link>
		<comments>http://zetblog.ru/programming/200910/python-passwords-list-for-bruteforce/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 11:56:19 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Brute Force]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=716</guid>
		<description><![CDATA[При написании в очередной раз программы для подбора паролей к чему-либо (исключительно в образовательных целях и для учёбы ;-) ) опять возникла необходимость в итераторе по заданному алфавиту. Т.е. необходимо написать класс, который мог бы генерировать пароли для последующей передачи их в программу, которая &#171;примеряла&#187; их к чему-надо. К чему &#8212; дело третье и сейчас [...]]]></description>
			<content:encoded><![CDATA[<p>При написании в очередной раз программы для подбора паролей к чему-либо (исключительно в образовательных целях и для учёбы ;-) ) опять возникла необходимость в итераторе по заданному алфавиту. Т.е. необходимо написать класс, который мог бы генерировать пароли для последующей передачи их в программу, которая &#171;примеряла&#187; их к чему-надо. К чему &#8212; дело третье и сейчас нас (вернее Вас) не волнует. В результате получился скромный класс, который приведён ниже со столь же скромными моими комментариями к нему :-).<br />
<span id="more-716"></span></p>
<p>Сам класс для перебора паролей ко всему и вся таков:</p>
<pre class="brush: python"># -*- coding: utf-8 -*-

EN = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
en = "abcdefghijklmnopqrstuvwxyz"
RU = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
ru = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
digits = "1234567890"
space = " "
p = ",.-!?;:'\"/()"
op = "+-*/:^()&lt;&gt;="
all_spec = "`~!@#$%^&amp;*-_=+\\|/?.&gt;,&lt; '\";:[]{}"

class ABCIterator:
    firstuse_flag = True
    stop = None

    def __init__(self, start="", stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec):
        assert len(abc) &gt; 0
        if start_len is not None:
            assert start_len &gt; 0
            #assert start == ""
            self.current_str = list(abc[0]*start_len)
        else:
            self.current_str = list(filter(lambda x: x in abc, start))
        if stop_len is not None:
            assert (start_len is None) or (start_len &lt;= stop_len)
            assert stop_len &gt; 0
            self.stop = list(abc[0]*(stop_len+1)) # т.к. итератор работает с полуотрезками
        else:
            if stop is not None: self.stop = list(filter(lambda x: x in abc, stop))
        self.abc = list(abc)

    def __iter__(self):
        return self

    def next(self):
        if (self.stop is not None) and (self.stop == self.current_str):
            raise StopIteration
        if self.current_str == []:
            self.current_str.append(self.abc[0])
            self.firstuse_flag = False
            return self.abc[0]
        elif self.firstuse_flag:
            self.firstuse_flag = False
            return "".join(self.current_str)
        offset = 0
        while offset &lt; len(self.current_str):
            if self.current_str[offset] != self.abc[-1]:
                self.current_str[offset] = self.abc[self.abc.index(self.current_str[offset])+1]
                # выпендрёшь для полуотрезка
                if (self.stop is not None) and (self.current_str == self.stop):
                    raise StopIteration
                return "".join(self.current_str)
            self.current_str[offset] = self.abc[0]
            offset += 1
        self.current_str = [self.abc[0]] + self.current_str
        # опять же оно же
        if (self.stop is not None) and (self.current_str == self.stop):
            raise StopIteration
        return "".join(self.current_str)
</pre>
<p>А таковы мои пояснения к нему:</p>
<ul>
<li><strong>firstuse_flag</strong> &#8212; свойство, которое указывает на то, что итератор используется впервые и не стоит производить итерацию, надо лишь вернуть текущее значени строки. Это нужно для того, чтобы в цикле не &#171;съедалось&#187; первое значение (напр., инициализировали итератор с начальной строкой &#171;aaa&#187;, а при 1й же итерации он вернул бы, без этого чудесного свойства, &#171;baa&#187;)</li>
<li><strong>stop</strong> &#8212; указывает на значение, на котором пора бы уже остановиться и вызвать исключение StopIteration. Если не задано (имеет значение None), то не пора, итератор будет бесконечным</li>
<li><strong>__init__(start=&#187;, stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec, **kwargs)</strong> &#8212; в общем то сам конструктор. <strong>start</strong> &#8212; начальное значение, <strong>stop</strong> &#8212; конечное, если не задано или идёт до начального, то итерации происходят бесконечно. Можно так же задать начальную и конечную длину, место конкретных значений с помощью <strong>start_len</strong> и <strong>stop_len</strong>. Если задана длина и начальные значения, то приоритет будет иметь длина, что можно легко исправить, если для кого-то это критично. <strong>abc</strong> &#8212; алфавит, над которым будут производиться итерации.</li>
<li><strong>__iter__()</strong> &#8212; необходимо для того чтобы класс был полноценным итератором.</li>
<li><strong>next()</strong> &#8212; возвращает следующую строку, в общем-то этот метод так же необходим для того чтобы класс был итератором.</li>
</ul>
<p>Пример использования:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="sy0">&gt;&gt;&gt;</span> <span class="kw1">for</span> i <span class="kw1">in</span> ABCIterator<span class="br0">&#40;</span>start_len=<span class="nu0">1</span>, stop_len=<span class="nu0">3</span>, abc=<span class="st0">&quot;abc&quot;</span><span class="br0">&#41;</span>:
... &nbsp; &nbsp; <span class="me1">i</span>
...
<span class="st0">'a'</span>
<span class="st0">'b'</span>
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
<span class="st0">'bcc'</span>
<span class="st0">'ccc'</span>
<span class="sy0">&gt;&gt;&gt;</span></div>
</div>
</pre>
<p>Ну, как-то так оно и работает. Если кому-то что-то непонятно, то могу объяснить подробнее. В общем как обычно, всё в комменты ;-). Неплохо было бы ещё реализовать преобразование чисел в строки и наоборот, но это позже&#8230; может быть.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200910/python-passwords-list-for-bruteforce/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Python: файловый интерпретатор.</title>
		<link>http://zetblog.ru/programming/200905/python-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bf%d1%80%d0%b5%d1%82%d0%b0%d1%82%d0%be%d1%80/</link>
		<comments>http://zetblog.ru/programming/200905/python-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bf%d1%80%d0%b5%d1%82%d0%b0%d1%82%d0%be%d1%80/#comments</comments>
		<pubDate>Wed, 20 May 2009 12:46:23 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=710</guid>
		<description><![CDATA[Очередной бестолковый велосипед от СГУ. Требуется написать &#171;интерпретатор&#187;, который умел бы работать с файлами. Так же умел бы исполнять сторонние скрипты. Работа с файлами заключается в следующих функциях &#8212; открыть на запись, открыть на чтение, закрыть файл, читать из файла, читать n байт, записать в файл, читать в буфер, записать из буфера в файл, сместиться [...]]]></description>
			<content:encoded><![CDATA[<p>Очередной бестолковый велосипед от СГУ. Требуется написать &#171;интерпретатор&#187;, который умел бы работать с файлами. Так же умел бы исполнять сторонние скрипты. Работа с файлами заключается в следующих функциях &#8212; открыть на запись, открыть на чтение, закрыть файл, читать из файла, читать n байт, записать в файл, читать в буфер, записать из буфера в файл, сместиться на определённую позицию.<br />
<span id="more-710"></span></p>
<p>По сути получается некая прослойка между консолью и функциями самого языка программирования. В C++ пришлось наверное помучиться над этим (хотя ничего сложного, главное &#8212; знания), в python&#8217;е всё как всегда ;-).</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># -*- coding: utf-8 -*-</span></p>
<p><span class="kw1">import</span> <span class="kw3">sys</span></p>
<p><span class="kw1">class</span> MyFile:<br />
<span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
<span class="kw2">self</span>.<span class="me1">name</span> = <span class="kw2">None</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span> = <span class="kw2">None</span><br />
<span class="kw2">self</span>.<span class="me1">flags</span> = <span class="kw2">None</span><br />
<span class="kw2">self</span>.<span class="me1">buffer</span> = <span class="st0">&quot;&quot;</span></p>
<p><span class="kw1">def</span> <span class="kw2">open</span><span class="br0">&#40;</span><span class="kw2">self</span>, fname, flags<span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Opening %s in mode %s.&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>fname, flags<span class="br0">&#41;</span><br />
<span class="kw2">self</span>.<span class="me1">name</span> = fname<br />
<span class="kw2">self</span>.<span class="me1">flags</span> = flags<br />
<span class="kw2">self</span>.<span class="me1">desc</span> = <span class="kw2">open</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">name</span>, flags<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> write<span class="br0">&#40;</span><span class="kw2">self</span>, data<span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Writing data in file.&quot;</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">write</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> writeFromBuffer<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">bytes</span>=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
<span class="kw1">if</span> <span class="kw3">bytes</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
<span class="kw3">bytes</span> = <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Writing data in file from buffer.&quot;</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#91;</span>:<span class="kw3">bytes</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Wrote %d bytes.&quot;</span> <span class="sy0">%</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#91;</span>:<span class="kw3">bytes</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="kw2">self</span>.<span class="me1">buffer</span> = <span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#91;</span><span class="kw3">bytes</span>:<span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> read<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">bytes</span>=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Reading from file.&quot;</span><br />
<span class="kw1">if</span> <span class="kw3">bytes</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">else</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="kw3">bytes</span><span class="br0">&#41;</span><br />
lr = <span class="kw2">len</span><span class="br0">&#40;</span>r<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Read %d bytes from file: <span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>.&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>lr, r<span class="br0">&#41;</span><br />
<span class="kw1">return</span> r</p>
<p><span class="kw1">def</span> writeToBuffer<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">bytes</span>=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Reading from file to buffer.&quot;</span><br />
<span class="kw1">if</span> <span class="kw3">bytes</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">else</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="kw3">bytes</span><span class="br0">&#41;</span><br />
lr = <span class="kw2">len</span><span class="br0">&#40;</span>r<span class="br0">&#41;</span><br />
<span class="kw2">self</span>.<span class="me1">buffer</span> += r<br />
<span class="kw1">print</span> <span class="st0">&quot;Read %d bytes from file: <span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>.&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>lr, r<span class="br0">&#41;</span><br />
<span class="kw1">return</span> r</p>
<p><span class="kw1">def</span> clearBuffer<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
<span class="kw2">self</span>.<span class="me1">buffer</span> = <span class="st0">&quot;&quot;</span></p>
<p><span class="kw1">def</span> close<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Closing file.&quot;</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> seek<span class="br0">&#40;</span><span class="kw2">self</span>, position<span class="br0">&#41;</span>:<br />
position = <span class="kw2">int</span><span class="br0">&#40;</span>position<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Seting seek in file to position %d&quot;</span> <span class="sy0">%</span> position<br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">seek</span><span class="br0">&#40;</span>position<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> process<span class="br0">&#40;</span>f<span class="br0">&#41;</span>:<br />
f = <span class="kw2">open</span><span class="br0">&#40;</span>f, <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span><br />
mf = MyFile<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">for</span> line <span class="kw1">in</span> f:<br />
<span class="kw2">eval</span><span class="br0">&#40;</span><span class="st0">&quot;mf.&quot;</span> + line<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
args = <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span>1:<span class="br0">&#93;</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>args<span class="br0">&#41;</span> <span class="sy0">&amp;</span>gt<span class="sy0">;</span> 0:<br />
<span class="kw1">for</span> arg <span class="kw1">in</span> args:<br />
<span class="kw1">try</span>:<br />
process<span class="br0">&#40;</span>arg<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;!!! %s processed successfully. !!!&quot;</span> <span class="sy0">%</span> arg<br />
<span class="kw1">except</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;!!! Error while processing script %s. !!!&quot;</span> <span class="sy0">%</span> arg<br />
<span class="kw1">else</span>:<br />
action = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;q &#8212; quit&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;open(fname) &#8212; open file&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;write(data) &#8212; write data in file&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;read([bytes]) &#8212; read data from file&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;seek(position) &#8212; set seek in file to position&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;close() &#8212; close file&quot;</span><br />
f = MyFile<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">while</span> <span class="kw2">True</span>:<br />
<span class="kw1">try</span>:<br />
<span class="kw2">eval</span><span class="br0">&#40;</span><span class="st0">&quot;f.&quot;</span> + <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;&amp;gt; &quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">except</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Error.&quot;</span><br />
<span class="kw1">else</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Ok.&quot;</span></div>
</div>
<p>Если мы хотим работать в интерактивном режиме &#8212; то просто выполняем скрипт, если хотим обработать скрипты &#8212; передаём их имена в параметрах программы. Например:</p>
<div class="codesnip-container" >$./main.py 1.scr 2.scr 3.scr</div>
<p>На сегодня, пожалуй, хватит с меня постов, подожду пока эти оценят ;-).</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200905/python-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bf%d1%80%d0%b5%d1%82%d0%b0%d1%82%d0%be%d1%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: генерация группы ключей.</title>
		<link>http://zetblog.ru/programming/200905/python-%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%8b-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b9/</link>
		<comments>http://zetblog.ru/programming/200905/python-%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%8b-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b9/#comments</comments>
		<pubDate>Wed, 20 May 2009 12:23:34 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[криптография]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=707</guid>
		<description><![CDATA[Опять делюсь универскими наработками. Задача в общем то примитивная (или по крайней мере её реализация). Надо сгенерировать N равнозначных ключей для шифрования/дешифрования сообщения. Т.е., генерируем 10 ключей, шифруем сообщение любым из этих 10, расшифровываем так же любым из этих 10. Например, зашифровали пятым ключом, расшифровали третьим, или десятым. Для реализации поставленной задачи опять прибегнем к [...]]]></description>
			<content:encoded><![CDATA[<p>Опять делюсь универскими наработками. Задача в общем то примитивная (или по крайней мере её реализация). Надо сгенерировать N равнозначных ключей для шифрования/дешифрования сообщения. Т.е., генерируем 10 ключей, шифруем сообщение любым из этих 10, расшифровываем так же любым из этих 10. Например, зашифровали пятым ключом, расшифровали третьим, или десятым.<br />
<span id="more-707"></span></p>
<p>Для реализации поставленной задачи опять прибегнем к ксору aka XOR, исключающее или, почти <a href="/programming/200812/%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8F-%D1%88%D0%B8%D1%84%D1%80-%D0%B2%D0%B5%D1%80%D0%BD%D0%B0%D0%BC%D0%B0/">шифр Вернама</a>. Почти &#8212; потому что длина ключа у нас по сути не равна длине сообщения. Алгоритм будет таков:</p>
<ol>
<li>Дано начальное значение ikey. В общем то это и будет на самом деле ключ, который используется в шифровании и расшифровке, просто он будет &#171;спрятан&#187; в сгенерированных ключах.</li>
<li>Генерируем 10 случайных строк по длине равных ключу ikey.</li>
<li>Для каждой строки из предыдущего пункта выполняем: xor(A, ikey) + A. Полученные строки и будут нашими ключами.</li>
</ol>
<p>Теперь для шифрования нам необходимо предварительно обработать введёный ключ и извлечь из него ikey. Это можно сделать поксорив первую половину ключа со второй. И с помощью ikey уже шифровать или расшифровывать сообщение.</p>
<p>Реализацию ксора в python нашёл на просторах инета (выглядит довольно красиво, я пока так не умею :-)), остальное писал сам. Вот исходник:</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># -*- coding: utf-8 -*-</span></p>
<p><span class="kw1">import</span> <span class="kw3">random</span>, <span class="kw3">itertools</span>, <span class="kw3">struct</span></p>
<p><span class="kw1">def</span> generate_strings<span class="br0">&#40;</span>ikey, q=10<span class="br0">&#41;</span>:<br />
keys = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>q<span class="br0">&#41;</span>:<br />
<span class="co1">#print &quot;%d.&quot; % i,</span><br />
keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">for</span> j <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>ikey<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
<span class="co1">#keys[i] += hex(random.randint(0, 15))[2 : ]</span><br />
keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> += <span class="kw2">chr</span><span class="br0">&#40;</span><span class="kw3">random</span>.<span class="me1">randint</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">255</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="co1">#print keys[i]</span><br />
<span class="kw1">return</span> keys</p>
<p><span class="kw1">def</span> xor <span class="br0">&#40;</span>s, key<span class="br0">&#41;</span>:<br />
key = <span class="kw3">itertools</span>.<span class="me1">cycle</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span><br />
<span class="kw1">return</span> <span class="st0">&#187;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="kw2">chr</span><span class="br0">&#40;</span><span class="kw2">ord</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span> ^ <span class="kw2">ord</span><span class="br0">&#40;</span>y<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">for</span> <span class="br0">&#40;</span>x,y<span class="br0">&#41;</span> <span class="kw1">in</span> <span class="kw3">itertools</span>.<span class="me1">izip</span><span class="br0">&#40;</span>s, key<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> generate_keys<span class="br0">&#40;</span>ikey<span class="br0">&#41;</span>:<br />
keys = generate_strings<span class="br0">&#40;</span>ikey<span class="br0">&#41;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>keys<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = xor<span class="br0">&#40;</span>keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span>, ikey<span class="br0">&#41;</span> + keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="co1">#xor(keys[i], b) + b</span><br />
<span class="kw1">return</span> keys</p>
<p><span class="kw1">def</span> bs2s<span class="br0">&#40;</span>bs<span class="br0">&#41;</span>:<br />
ss = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> bs:<br />
s = <span class="kw2">hex</span><span class="br0">&#40;</span><span class="kw2">ord</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#91;</span>2 : <span class="br0">&#93;</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span> == <span class="nu0">1</span>:<br />
ss += <span class="st0">&quot;0&quot;</span><br />
ss += s<br />
<span class="kw1">return</span> ss</p>
<p><span class="kw1">def</span> s2bs<span class="br0">&#40;</span>ss<span class="br0">&#41;</span>:<br />
bs = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>0, <span class="kw2">len</span><span class="br0">&#40;</span>ss<span class="br0">&#41;</span>, 2<span class="br0">&#41;</span>:<br />
bs += <span class="kw2">chr</span><span class="br0">&#40;</span><span class="kw2">int</span><span class="br0">&#40;</span>ss<span class="br0">&#91;</span>i : i +2<span class="br0">&#93;</span>, 16<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">return</span> bs</p>
<p><span class="kw1">def</span> restore_key<span class="br0">&#40;</span>key<span class="br0">&#41;</span>:<br />
c = <span class="kw2">len</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span> / 2<br />
<span class="kw1">return</span> xor<span class="br0">&#40;</span>key<span class="br0">&#91;</span> : c<span class="br0">&#93;</span>, key<span class="br0">&#91;</span>c : <span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
action = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Select action:<span class="es0">\n</span>g &#8212; generate keys<span class="es0">\n</span>c &#8212; encrypt or decrypt file<span class="es0">\n</span>q &#8212; quit&quot;</span><br />
<span class="kw1">while</span> action <span class="sy0">!</span>= <span class="st0">&quot;q&quot;</span>:<br />
action = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;&amp;gt; &quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">if</span> action == <span class="st0">&quot;g&quot;</span>:<br />
ikey = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter initial key value: &quot;</span><span class="br0">&#41;</span><br />
keys = generate_keys<span class="br0">&#40;</span>ikey<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Generated keys:&quot;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>keys<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;%d. %s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>i, bs2s<span class="br0">&#40;</span>keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">elif</span> action == <span class="st0">&quot;c&quot;</span>:<br />
f_in_name = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter input file name: &quot;</span><span class="br0">&#41;</span><br />
f_out_name = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter output file name: &quot;</span><span class="br0">&#41;</span><br />
key = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter key: &quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">try</span>:<br />
key = restore_key<span class="br0">&#40;</span>s2bs<span class="br0">&#40;</span>key<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
f = <span class="kw2">open</span><span class="br0">&#40;</span>f_in_name, <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span><br />
c = xor<span class="br0">&#40;</span>f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, key<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
f = <span class="kw2">open</span><span class="br0">&#40;</span>f_out_name, <span class="st0">&quot;wb&quot;</span><span class="br0">&#41;</span><br />
f.<span class="me1">write</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">except</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Errors :-(.&quot;</span><br />
<span class="kw1">elif</span> action <span class="sy0">!</span>= <span class="st0">&quot;q&quot;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Invalid action.&quot;</span></div>
</div>
<p>Единственная поправка к алгоритму, который я описал &#8212; ключи перед выводом я перевожу в шестнадцатиричное число, чтобы не хранить ключи в бинарном виде, ну и после ввода так же перевожу обратно. На этом всё.</p>
<p>Ссылки к статье:<br />
<a href="http://code.activestate.com/recipes/496970/">http://code.activestate.com/recipes/496970/</a> &#8212; &#171;Recipe 496970: xor for strings&#187;.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200905/python-%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%8b-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: Пример использования ORM Doctrine.</title>
		<link>http://zetblog.ru/programming/200905/php-orm-doctrine-simple-example/</link>
		<comments>http://zetblog.ru/programming/200905/php-orm-doctrine-simple-example/#comments</comments>
		<pubDate>Wed, 20 May 2009 10:35:25 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=700</guid>
		<description><![CDATA[В данном посте рассмотрим простенький пример использования ORM, а именно, Doctrine. Если кто не в курсе, то ORM (Object-Relational Mapping, объектно-реляционная проекция) &#8212; такая штука, которая обеспечивают классам прозрачный доступ к базе данных. Правда не всяким классам, а тем, которые представляют описание нашей модели данных. В общем мне бы пару лет назад узнать о такой [...]]]></description>
			<content:encoded><![CDATA[<p>В данном посте рассмотрим простенький пример использования ORM, а именно, Doctrine. Если кто не в курсе, то ORM (Object-Relational Mapping, объектно-реляционная проекция) &#8212; такая штука, которая обеспечивают классам прозрачный доступ к базе данных. Правда не всяким классам, а тем, которые представляют описание нашей модели данных. В общем мне бы пару лет назад узнать о такой штуке, может быть я и не забросил изучение php, и вообще, много чего полезного сделал :D. Если кто-то знаком с паттернами проектирования, то можно сказать, что Doctrine соответствует шаблону Active Record. К своему стыду, сам я не знаком с ними, поэтому ничего конкретней сказать не могу пока что :-).</p>
<p>Кстати, мы уже затрагивали мельком тему ORM, но только для python. Можете посмотреть <a href="http://zetblog.ru/tag/sqlalchemy/">тут</a> про SQLAlchemy.</p>
<p>Далее будет рассмотрен пример написания модуля на php с использованием ORM Doctrine для отправки личных сообщений между пользователей.<br />
<span id="more-700"></span></p>
<p>Для начала определимся с нашей таблицей. Я решил использовать всего одну табличку, и для каждого сообщения так же хранить только одну запись в БД. И так, поля таблицы выглядят у меня примерно следующим образом:</p>
<ul>
<li>id &#8212; id сообщения;</li>
<li>uid_from &#8212; id отправившего пользователя;</li>
<li>uid_to &#8212; id получателя;</li>
<li>title &#8212; заголовок сообщения;</li>
<li>text &#8212; текст сообщения;</li>
<li>flag_unread &#8212; флаг нового сообщения;</li>
<li>flag_del_from &#8212; признак удалённого сообщения из исходящих;</li>
<li>flag_del_to &#8212; признак удалённого сообщения из входящих;</li>
<li>date &#8212; дата отправки в формате unix timestamp;</li>
</ul>
<p>На этом этап проектирования у меня закончился :). Теперь перейдём к технической стороне вопроса.</p>
<p>Качаем тот самый Doctrine (ссылка в конце поста), находим в архиве директорию, где лежит файл Doctrine.php и копируем всё содержимое этого каталога в отдельную папку в нашем проекте (я скопировал в doctrine). Следуя документации, создаём файл bootstrap.php в корне проекта с таким содержанием:</p>
<pre class=".brush: php">&lt;?php
require_once(dirname(__FILE__) . '/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();
$manager->setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE);
$manager->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, true);
$manager->setAttribute(Doctrine::ATTR_EXPORT, Doctrine::EXPORT_ALL);
$manager->setAttribute(Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_ALL);
$manager->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true);
$user = 'tst';
$password = 'tst';
$host = 'localhost';
$db = 'tst';
$dsn = "mysql://$user:$password@$host/$db";
$conn = Doctrine_Manager::connection($dsn);
Doctrine::loadModels('models');
?></pre>
<p>Тут настраивается подключение к БД и некоторые параметры (&#171;ленивый&#187; способ загрузки моделей, валидация данных и т.п.). Последняя строчка указывает Doctrine где искать наши модели.</p>
<p>Теперь в корне проекта создаём папку models и в ней файл PrivateMessage.php. Учтите, что имя файла и класса, который описан в нём, должны совпадать. Вот как у меня выглядит этот файл:</p>
<pre class=".brush: php">&lt;?php
class PrivateMessage extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('uid_from', 'integer', 8, array(
				'unsigned' => true,
				'notnull' => true
			)
		);
        $this->hasColumn('uid_to', 'integer', 8, array(
				'unsigned' => true,
				'notnull' => true
			)
		);
        $this->hasColumn('title', 'string', 128);
        $this->hasColumn('text', 'string', 255);
        $this->hasColumn('flag_unread', 'boolean', array(
        		'default' => false,
				'notnull' => true
			)
		);
	$this->hasColumn('flag_del_from', 'boolean', array(
				'notnull' => true,
				'default' => false
			)
		);
	$this->hasColumn('flag_del_to', 'boolean', array(
				'notnull' => true,
				'default' => false
			)
		);
        $this->hasColumn('date', 'integer', 8, array(
        		'notnull' => true,
				'default' => time()
			)
		);
    }
}
?></pre>
<p>Тут мы не описали поле id, т.к. Doctrine создаст его автоматически, если не указано других первичных ключей (primary key). Так же в таблице не указаны индексов, что не есть хорошо. Неплохо было бы сделать их для полей uid_from и uid_to хотя бы. Но не сделаем, ибо лень, как-нибудь в другой раз ;-).</p>
<p>Следующим шагом создаём в корне проекта файл test.php, в котором будут описаны основные функции для работы с личными сообщениями и некоторый код для демонстрации функционала. Вот содержимое этого файла:</p>
<pre class=".brush: php">&lt;?php
require_once('bootstrap.php');
$conn->export->exportClasses(array('PrivateMessage'));
#FIXME: Set current user ID from session.
$curr_uid = 1;
function get_messages($inbox, $uid) {
	/*
	 * If $inbox == true then returns inbox of user $uid,
	 * else returns outbox.
	 */
	if($inbox) {
		$q = 'pm.uid_to = ? AND pm.flag_del_to = ?';
	} else {
		$q = 'pm.uid_from = ? AND pm.flag_del_from = ?';
	}
	return Doctrine_Query::create()
    	->from('PrivateMessage pm')
    	->where($q, array($uid, 0))
    	->fetchArray();
}

function get_message($id, $uid) {
	$q = Doctrine_Query::create()
    	->from('PrivateMessage pm')
    	->where('pm.id = ? AND (pm.uid_from = ? OR pm.uid_to = ?)', array($id, $uid, $uid));
    	$q = $q->fetchArray();
    	if(count($q)) {
    		if($uid == $q[0]['uid_to'] &#038;&#038; $q[0]['flag_unread']) {
    			Doctrine_Query::create()
				    ->update('PrivateMessage pm')
    				->set('pm.flag_unread', '?', false)
 			   		->where('pm.id = ?', $q[0]['id'])
 			   		->execute();
    		}
    		return $q[0];
    	} else {
    		return false;
    	}
}

function delete_messages($ids, $uid) {
	/*
	 * $ids - array of ids of messages, that will be deleted.
	 * $uid - current user id.
	 * P.S. Broken English - is the most popular language in the world ;-).
	 */
	foreach($ids as $id) {
		Doctrine_Query::create()
			->update('PrivateMessage pm')
			->set('pm.flag_del_to', '?', true)
 			->where('pm.id = ? AND pm.uid_to = ?', array($id, $uid))
 			->execute();
 		Doctrine_Query::create()
			->update('PrivateMessage pm')
			->set('pm.flag_del_from', '?', true)
 			->where('pm.id = ? AND pm.uid_from = ?', array($id, $uid))
 			->execute();
	}
	Doctrine_Query::create()
		->delete('PrivateMessage pm')
 		->where('pm.flag_del_from = 1 AND pm.flag_del_to = 1')
 		->execute();
}

function send_message($to, $title, $text, $uid) {
	$pm = new PrivateMessage();
	$pm->uid_from = $uid;
	$pm->uid_to = $to;
	$pm->title = $title;
	$pm->text = $text;
	$pm->flag_unread = true;
	// Если хранить в исходящих ненадо,
	// то можно установить следующий флаг в true.
	$pm->flag_del_from = false;
	$pm->flag_del_to = false;
	$pm->save();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru" xml:lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
&lt;?php
echo 'Current user:' . $curr_uid;
// Send message section.
if((int)@$_REQUEST['to'] &#038;&#038; !@empty($_REQUEST['title']) &#038;&#038; !@empty($_REQUEST['text'])) {
	send_message((int)$_REQUEST['to'], $_REQUEST['title'], $_REQUEST['text'], $curr_uid);
}
// End of send message section.

// Delete messages section.
if(@count($_REQUEST['del_messages'])) {
	echo '
<pre>';
	delete_messages($_REQUEST['del_messages'], $curr_uid);
	echo '</pre>
<p>';<br />
}<br />
// End of delete messages section.</p>
<p>// Inbox section.<br />
?></p>
<hr/>Inbox:</p>
<form name="del_messages" action="" method="post">
<table border="1">
<tr>
<td>Del</td>
<td>Message ID</td>
<td>Date</td>
<td>From</td>
<td>Title</td>
</tr>
<p>&lt;?php<br />
$m = get_messages(true, $curr_uid);<br />
foreach($m as $message) {<br />
	// Mark as bold unread messages.<br />
	if($message['flag_unread']) {<br />
		$b_open = '<b>';<br />
		$b_close = '</b>';<br />
	} else {<br />
		$b_open = '';<br />
		$b_close = '';<br />
	}<br />
	// End mark.<br />
	echo "<br />
<tr>
<td>
<input type=\"checkbox\" name=\"del_messages[]\" value=\"$message[id]\"/></td>
<td><a href=\"?message_id=$message[id]\">$b_open$message[id]$b_close</a></td>
<td>$b_open" . date('d.m.y H:i', $message['date']) . "$b_close</td>
<td>$b_open$message[uid_from]$b_close</td>
<td>$b_open$message[title]$b_close</td>
</tr>
<p>";<br />
}<br />
?></p>
<tr>
<td colspan="5">
<input type="submit" value="Delete selected"/></td>
</tr>
</table>
<p>&#038;lt?php<br />
// End of inbox section.</p>
<p>// Outbox section.<br />
?></p>
<hr/>Outbox:</p>
<table border="1">
<tr>
<td>Del</td>
<td>Message ID</td>
<td>Date</td>
<td>To</td>
<td>Title</td>
</tr>
<p>&lt;?php<br />
$m = get_messages(false, $curr_uid);<br />
foreach($m as $message) {<br />
	// Mark as bold unread messages.<br />
	if($message['flag_unread']) {<br />
		$b_open = '<b>';<br />
		$b_close = '</b>';<br />
	} else {<br />
		$b_open = '';<br />
		$b_close = '';<br />
	}<br />
	// End mark.<br />
	echo "<br />
<tr>
<td>
<input type=\"checkbox\" name=\"del_messages[]\" value=\"$message[id]\"/></td>
<td><a href=\"?message_id=$message[id]\">$b_open$message[id]$b_close</a></td>
<td>$b_open" . date('d.m.y H:i', $message['date']) . "$b_close</td>
<td>$b_open$message[uid_to]$b_close</td>
<td>$b_open$message[title]$b_close</td>
</tr>
<p>";<br />
}<br />
?></p>
<tr>
<td colspan="5">
<input type="submit" value="Delete selected"/></td>
</tr>
</form>
</table>
<p>?><br />
// End of outbox section.</p>
<p>// View message section.<br />
if((int)@$_REQUEST['message_id']) {<br />
	$m = get_message($_REQUEST['message_id'], $curr_uid);<br />
	if($m !== false) {<br />
		echo "<br />
<hr/>View message #$m[id]:";<br />
		echo '<br />
<table border="1">';<br />
		echo "<br />
<tr>
<td>From:</td>
<td>$m[uid_from]</td>
</tr>
<tr>
<td>To:</td>
<td>$m[uid_to]</td>
</tr>
<tr>
<td>Title:</td>
<td>$m[title]</td>
</tr>
<tr>
<td>Message:</td>
<td>$m[text]</td>
</tr>
</table>
<p>";<br />
	}<br />
}<br />
// End of view message section.</p>
<p>// Send message section.<br />
echo "</p>
<hr/>New message:</p>
<table border="1">
<form action="" method="post" name="send_message">
<tr>
<td>From:</td>
<td>$curr_uid</td>
</tr>
<tr>
<td>To:</td>
<td>
<input name="to"/></td>
</tr>
<tr>
<td>Title:</td>
<td>
<input name="title"/></td>
</tr>
<tr>
<td>Message:</td>
<td><textarea name="text"></textarea></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="send message"></td>
</tr></form>
</table>
<p>";<br />
// End of send message section.<br />
?><br />
</body><br />
</html></pre>
<p>$conn->export->exportClasses(array(&#8216;PrivateMessage&#8217;)) &#8212; это строка создаст таблицу private_messaages, если таковой ещё нет. Так что можно её перенести в установочный скрипт, но поскольку у нас нет такого, то мы её оставим.<br />
$curr_uid &#8212; эта переменная по идее должна браться из сессии. Как она должна называться в сессии я не знал, поэтому присвоил ей значение в коде 1.<br />
get_messages($inbox, $uid) &#8212; возвращает все входящие сообщения пользователя $uid, если $inbox равна true, иначе &#8212; исходящие. Неплохо было бы добавить лимит на выборку записей (например, с 1й по 20ю, с 21й по 40ю), но поскольку этот модуль нигде применять не планирую, то и доделывать его нет желания. Если кому то надо &#8212; пишите в комменты ;-).<br />
get_message($id, $uid) &#8212; возвращает сообщение $id, $uid передаётся во все функции для проверки принадлежности сообщений текущему пользователю. Ещё раз повторю, идентификатор ползьователя должен браться из сессии.<br />
delete_messages($ids, $uid) &#8212; $ids &#8212; массив id&#8217;шников сообщений, которые надо удалить. Реально удаляются записи из БД только те, у которых flag_del_from и flag_del_to равны 0.<br />
send_message($to, $title, $text, $uid) &#8212; $to &#8212; id получателя, $uid &#8212; отправителя, остально думаю понятно.<br />
Дальше по коду идёт часть с html-выводом и обработкой переданных парамтеров, так что ничего интересного. Код по моему везде достаточно просто, так что подробно объяснять не стал. Если вопросы остались &#8212; в комменты.</p>
<p>P.S. Это моя первая попытка сделать что-либо с использованием Doctrine :).<br />
Ссылки к статье:<br />
<a href="http://ru.wikipedia.org/wiki/ORM">http://ru.wikipedia.org/wiki/ORM</a> &#8212; ORM;<br />
<a href="http://www.doctrine-project.org/">http://www.doctrine-project.org/</a> &#8212; официальный сайт проекта Doctrine.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200905/php-orm-doctrine-simple-example/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

