tag:zed.0xff.me,2008:/posts
zed.0xff.me
2014-07-29T21:33:40Z
Enki
Andrey "Zed" Zaikin
zed@0xff.me
tag:zed.0xff.me,2008:Post/93
2015-01-16T12:00:00Z
2014-05-09T10:12:55Z
Телефонное интервью в Google №1
<p>(на самом деле не первое, а второе, первое было успешно провалено аж 4 года назад, из-за перенервничания)</p>
<p>Итак, сначала девушка-HR мне написала еmail, в котором мы договорились когда она мне позвонит по телефону. (все общение на английском языке конечно)</p>
<p>Потом она позвонила, спросила куда я хочу – в Дублин или Цюрих? Я удивился, ибо про Цюрих не знал ни сном ни духом… Думал только в Дублин зовут.</p>
<p>Еще сказала что у них есть Software Engineers, а есть Systems Engineers, короче техподдержка серверов и сервисов. Спросила меня куда я хочу, я сказал что не уверен. (но видимо мне таки ближе Systems Engineers :))</p>
<p>Потом начались технические вопросы, порядка 20 штук, довольно элементарные, разделенные на разделы:</p>
<ol>
<li>админство *nix</li>
<li>алгоритмы</li>
<li>структуры данных</li>
</ol>
<p>Вопросы из разряда “что такое inode”, “сколько бит занимают права владельца файла в <span class="caps">UNIX</span> <span class="caps">ACL</span>”, “оцените время выполнения qsearch в worst case случае” (на последний я не ответил, ибо во всяких этих ваших N*log(N) не силен чуть более чем никак)</p>
<p>Вобщем на 1 вопрос я не ответил совсем, еще на 1 ответил на 2/3, а на все остальные ответил на 97-110% ;)</p>
<p>HR сказала что передаст мои ответы и резюме дальше по конвейеру и со мной свяжутся..</p>
tag:zed.0xff.me,2008:Post/94
2014-07-29T21:33:00Z
2014-07-29T21:33:40Z
Дневник бортинженера авиакомпании "B***Y"
<p>(все персонажи вымышлены, все совпадения с реальными личностями случайны)</p>
<p>Иногда пилоты обращаются ко мне<br />
П: А вот если мы повернем сейчас на 17 градусов влево, то у нас крыло не отвалится?<br />
Я: Хорошо что спросили. Отвалится. Давайте сейчас мои ребята выйдут на крыло, суперклеем намажут, а вы потом вправо повернете, и порезче! Кружок на месте сделаем, заодно и крыло подклеим, и повернем куда надо.<br />
П: ОК</p>
<p>Иногда приходят списки пассажиров вот такого вида:<br />
1. Иванов А.А., муж., Москва<br />
2. Сидорова Е.И., жен., С.Петербург<br />
3. Ъорлщхж М.Ф.У., аъы., Альфа-Центавра<br />
4. Макаров И.А., муж., Курган<br />
А на месте пассажира №3 либо пусто, либо обычный человек сидит. :(<br />
Вот такие они, поставщики данных о пассажирах.</p>
<p>Есть у нас и стюардессы, кои обязаны пассажиров успокаивать, всяческие их потребности удовлетворять, а также быть связующим звеном между пассажирами и экипажем.<br />
Пассажиры бывают разные. Один например глянет в иллюминатор, а там крыло отваливаться начинает, или еще какая напасть, так он тихо подзовет стюардессу, покажет пальчиком в окно, стюардесса передаст быстренько экипажу, мои ребята выбегут, подклеят там чегонить изолентой, мебельным степлером подстеплируют и все ОК. Летим дальше. Все довольны. Внимательному пассажиру бесплатный напиток.<br />
А другой, например, увидит что турбина горит, и давай орать благим матом на весь салон. Приходится бедным стюардессам отдуваться, врать что это он не двигатель горит, а это праздничный салют в честь дня рождения второго пилота, ура-ура! И давай хороводы водить! Вобщем, успокоили.<br />
А турбина? Ну погорит и перестанет, чай не последняя, у нас еще 5 штук есть )))</p>
<p>А недавно мы на лету избавились от карбюратора!!! Воткнули вместо него новенький инжектор (взяли подешевке на авторынке, от ВАЗ 21067, 2011 г.в.)<br />
Совсем другие ощущения!<br />
Какого хрена делал карбюратор на самолете… ума не приложу, вот так вот исторически сложилось.<br />
Это я еще молчу о том что когда я пришел на этот самолет, тут турбины вообще крутили специально обученные белки! O_O Воняяяялооооо…. Бо́льшая часть багажного отсека была забита кормом для белок. Они еще и дохли периодически, а другие размножались. Приходилось как-то поддерживать баланс рождаемости-смертности белок, утилизировать их какашки и тельца, следить за тем чтобы они не бегали по салону и не кусали пассажиров…<br />
Вобщем, инжектор – это просто манна небесная!</p>
<p>Туалет в самолете просто класс! Очень просторный (0.5х0.5х1.5м) и многофункциональный (поддерживаются функции PP и KK). Есть один небольшой нюанс. С вероятностью 10% незадачливого пассажира намертво присасывает к той самой дырке(давлением 4.04 psi), а с другой стороны, с вероятностью те же 10% оттуда прямо на пассажира начинает фонтанировать давлением 5.05 psi все его ужасное содержимое…<br />
Но, как отметили 80% пассажиров: “у нас все получилось”, так что не ремонт туалета пока не заморачиваемся.<br />
Подавляющее большинство довольно – значит все у нас хорошо!!</p>
<p>Авиакомпания у нас очень прибыльная. Потому что мы стремимся перевезти всех пассажиров, которые хотят лететь. Поэтому текущим ремонтом и даже усовершенствованием приходится заниматься в прямом смысле “на лету”.<br />
Хорошо что у нас есть команда бесстрашных инженеров-механиков. Но не всегда хорошо что бесстрашных.</p>
<p>Например, инженер по приборам – очень толковый парень. Благодаря ему мы наконец-то можем в реальном времени видеть сколько у нас горючего в баках, заряд аккумуляторов, текущую скорость, и даже выпускать шасси!! (раньше шасси было как у “кукурузника” например)<br />
Так вот, недавно он приделал классную штуку, альтиметр называется. “Теперь мы можем всегда знать нашу высоту полета! А не спрашивать языком жестов пролетающие мимо борта” – подумали мы.<br />
Свежевключенный альтиметр показал высоту что-то около 56млн км над уровнем моря. O_O<br />
– Какого моря?!<br />
– <a href="http://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D1%80%D0%B5_%D0%AE%D0%B6%D0%BD%D0%BE%D0%B5_(%D0%9C%D0%B0%D1%80%D1%81)">Южного</a>…<br />
– <code>#(*$&^&</code>#$(!!!!!<br />
Так и живем…</p>
<p>Еще есть специалист по тонкой электронике. Может из волоска и батарейки приемник собрать. Телевизионный.<br />
Взялся он как-то радар ремонтировать (что-то слишком много НЛО последнее время стал показывать)<br />
Ремонтировал-ремонтировал. “Готово” – говорит.<br />
Включаем. Работает. НЛО больше нет. Есть ОРТ. На радаре.<br />
<strong>facepalm</strong></p>
tag:zed.0xff.me,2008:Post/92
2013-05-06T17:28:00Z
2013-05-06T17:28:28Z
demangle MSVC, Delphi & C++Builder mangled function names with pure Ruby
<p>Ever wanted to convert <span style="background: #ffc; font-family:monospace; padding: 0 5px;">@afunc$qxzcupi</span> or <span style="background: #ffc; font-family:monospace; padding: 0 5px;">??3@YAXPAX@Z</span> to something more human-readable?</p>
<p>(ofcourse you wanted, and you know about <code>tdump.exe</code> and <code>undname.exe</code> :)</p>
<p>And now you can do it using pure ruby, thanks to <a href="https://github.com/zed-0xff/unmangler">unmangler</a> gem:</p>
<h3>Unmangling Borland mangled names</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">'</span><span class="k">unmangler</span><span class="dl">'</span></span><tt>
</tt><tt>
</tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">"</span><span class="k">@afunc$qxzcupi</span><span class="dl">"</span></span><tt>
</tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">"</span><span class="k">@Forms@TApplication@SetTitle$qqrx17System@AnsiString</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt><span class="c"># output:</span><tt>
</tt><span class="c"># afunc(const signed char, int *)</span><tt>
</tt><span class="c"># __fastcall Forms::TApplication::SetTitle(const System::AnsiString)</span><tt>
</tt></pre></td>
</tr></table>
<h3>Unmangling <span class="caps">MSVC</span> mangled names</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">'</span><span class="k">unmangler</span><span class="dl">'</span></span><tt>
</tt><tt>
</tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">"</span><span class="k">??3@YAXPAX@Z</span><span class="dl">"</span></span><tt>
</tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">"</span><span class="k">?AFXSetTopLevelFrame@@YAXPAVCFrameWnd@@@Z</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt><span class="c"># output:</span><tt>
</tt><span class="c"># void __cdecl operator delete(void *)</span><tt>
</tt><span class="c"># void __cdecl AFXSetTopLevelFrame(class CFrameWnd *)</span><tt>
</tt></pre></td>
</tr></table>
<h3>And now w/o arguments</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">'</span><span class="k">unmangler</span><span class="dl">'</span></span><tt>
</tt><tt>
</tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">"</span><span class="k">@Forms@TApplication@SetTitle$qqrx17System@AnsiString</span><span class="dl">"</span></span>, <span class="sy">:args</span> => <span class="pc">false</span><tt>
</tt><tt>
</tt><span class="c"># outputs "Forms::TApplication::SetTitle"</span><tt>
</tt><tt>
</tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">"</span><span class="k">?AFXSetTopLevelFrame@@YAXPAVCFrameWnd@@@Z</span><span class="dl">"</span></span>, <span class="sy">:args</span> => <span class="pc">false</span><tt>
</tt><tt>
</tt><span class="c"># outputs "AFXSetTopLevelFrame"</span><tt>
</tt></pre></td>
</tr></table>
<h3>Links</h3>
<ol>
<li><a href="http://rubygems.org/gems/unmangler">unmangler gem on rubygems.org</a></li>
<li><a href="https://github.com/zed-0xff/unmangler">unmangler sources on github.com</a></li>
</ol>
<p><span class="caps">TBD</span>: <span class="caps">GCC</span> support</p>
tag:zed.0xff.me,2008:Post/91
2013-01-17T07:44:00Z
2013-01-17T07:44:47Z
Advanced Ruby: percent-literals
<style>
table.percent-literals { margin-top: 1em }
table.percent-literals td { padding: 0.5em 1em; text-align: center }
table.percent-literals td a { color: blue }
</style>
<h3>most used %-literals:</h3>
<table class="t1 percent-literals">
<tr>
<th>% </th>
<th>code </th>
<th>result </th>
<th>description </th>
</tr>
<tr>
<td style="font: 12pt bold;"><code>%q</code> </td>
<td> <code>%q(all `quotes` 'are' "ok")</code> </td>
<td> <code>"all `quotes` 'are' \"ok\""</code> </td>
<td> creates <a href="http://www.ruby-doc.org/core/String.html">String</a> </td>
</tr>
<tr>
<td style="font: 12pt bold;"><code>%r</code> </td>
<td> <code>%r(i_am/a/regexp)</code> </td>
<td> <code>/i_am\/a\/regexp/</code> </td>
<td> creates <a href="http://www.ruby-doc.org/core/Regexp.html">Regexp</a> </td>
</tr>
<tr>
<td style="font: 12pt bold;"><code>%w</code> </td>
<td> <code>%w(abc def ghi)</code> </td>
<td> <code>["abc", "def", "ghi"]</code> </td>
<td> splits string into <a href="http://www.ruby-doc.org/core/Array.html">Array</a> </td>
</tr>
<tr>
<td style="font: 12pt bold;"><code>%x</code> </td>
<td> <code>%x(ls -a /tmp)</code> </td>
<td> <code>".\n..\nfile1\nfile2\n"</code> </td>
<td> alias of <a href="http://www.ruby-doc.org/core/Kernel.html#method-i-60">`cmd`</a> </td>
</tr>
</table>
<h3>highlighted</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="s"><span class="dl">%q(</span><span class="k">all `quotes` 'are' "ok"</span><span class="dl">)</span></span> => <span class="s"><span class="dl">"</span><span class="k">all `quotes` 'are' </span><span class="ch">\"</span><span class="k">ok</span><span class="ch">\"</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt><span class="rx"><span class="dl">%r(</span><span class="k">i_am/a/regexp</span><span class="dl">)</span></span> => <span class="rx"><span class="dl">/</span><span class="k">i_am</span><span class="ch">\/</span><span class="k">a</span><span class="ch">\/</span><span class="k">regexp</span><span class="dl">/</span></span><tt>
</tt><tt>
</tt><span class="s"><span class="dl">%w(</span><span class="k">abc def ghi</span><span class="dl">)</span></span> => [<span class="s"><span class="dl">"</span><span class="k">abc</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="k">def</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="k">ghi</span><span class="dl">"</span></span>]<tt>
</tt><tt>
</tt><span class="sh"><span class="dl">%x(</span><span class="k">ls -a /tmp</span><span class="dl">)</span></span> => <span class="s"><span class="dl">"</span><span class="k">.</span><span class="ch">\n</span><span class="k">..</span><span class="ch">\n</span><span class="k">file1</span><span class="ch">\n</span><span class="k">file2</span><span class="ch">\n</span><span class="dl">"</span></span><tt>
</tt></pre></td>
</tr></table>
<h3>interpolation</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># lowercase 'w': as-is</span><tt>
</tt><span class="s"><span class="dl">%w'</span><span class="k">a #{2+2} b</span><span class="dl">'</span></span> => [<span class="s"><span class="dl">"</span><span class="k">a</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="ch">\#</span><span class="k">{2+2}</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="k">b</span><span class="dl">"</span></span>] <tt>
</tt><tt>
</tt><span class="c"># uppercase 'W': interpolate</span><tt>
</tt><span class="s"><span class="dl">%W'</span><span class="k">a </span><span class="il"><span class="idl">#{</span><span class="i">2</span>+<span class="i">2</span><span class="idl">}</span></span><span class="k"> b</span><span class="dl">'</span></span> => [<span class="s"><span class="dl">"</span><span class="k">a</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="k">4</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="k">b</span><span class="dl">"</span></span>] <tt>
</tt><tt>
</tt><span class="c"># lowercase 'q': as-is</span><tt>
</tt><span class="s"><span class="dl">%q'</span><span class="k">a #{2+2} b</span><span class="dl">'</span></span> => <span class="s"><span class="dl">"</span><span class="k">a </span><span class="ch">\#</span><span class="k">{2+2} b</span><span class="dl">"</span></span> <tt>
</tt><tt>
</tt><span class="c"># uppercase 'Q': interpolate</span><tt>
</tt><span class="s"><span class="dl">%Q'</span><span class="k">a </span><span class="il"><span class="idl">#{</span><span class="i">2</span>+<span class="i">2</span><span class="idl">}</span></span><span class="k"> b</span><span class="dl">'</span></span> => <span class="s"><span class="dl">"</span><span class="k">a 4 b</span><span class="dl">"</span></span> <tt>
</tt></pre></td>
</tr></table>
<h3>other %-literals</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># %s: convert to symbol</span><tt>
</tt><span class="sy"><span class="dl">%s'</span><span class="k">foo</span><span class="dl">'</span></span> => <span class="sy">:foo</span> <tt>
</tt><tt>
</tt><span class="c"># %i: convert to array of symbols - not released yet, will be in Ruby 2.0 ?</span><tt>
</tt>%i<span class="s"><span class="dl">'</span><span class="k">foo bar baz</span><span class="dl">'</span></span> => [<span class="sy">:foo</span>, <span class="sy">:bar</span>, <span class="sy">:baz</span>]<tt>
</tt><tt>
</tt><span class="c"># '%' w/o any letter - alias for %Q</span><tt>
</tt><span class="s"><span class="dl">%'</span><span class="k">a </span><span class="il"><span class="idl">#{</span><span class="i">2</span>+<span class="i">2</span><span class="idl">}</span></span><span class="k"> b</span><span class="dl">'</span></span> => <span class="s"><span class="dl">"</span><span class="k">a 4 b</span><span class="dl">"</span></span><tt>
</tt></pre></td>
</tr></table>
tag:zed.0xff.me,2008:Post/90
2013-01-15T23:18:00Z
2013-01-15T23:18:51Z
Advanced Ruby: break(value) & next(value)
<h2>1. break(value)</h2>
<p><code>break</code> accepts a value that supplies the result of the expression it is “breaking” out of:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"> result = [<span class="i">1</span>, <span class="i">2</span>, <span class="i">3</span>].each <span class="r">do</span> |value|<tt>
</tt> <span class="r">break</span> value * <span class="i">2</span> <span class="r">if</span> value.even?<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> p result <span class="c"># prints 4</span><tt>
</tt></pre></td>
</tr></table>
<h2 style="margin-top:2em;">2. next(value)</h2>
<p><code>next</code> accepts an argument that can be used the result of the current block iteration:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"> result = [<span class="i">1</span>, <span class="i">2</span>, <span class="i">3</span>].map <span class="r">do</span> |value|<tt>
</tt> <span class="r">next</span> value <span class="r">if</span> value.even?<tt>
</tt><tt>
</tt> value * <span class="i">2</span><tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> p result <span class="c"># prints [2, 2, 6]</span><tt>
</tt></pre></td>
</tr></table>
tag:zed.0xff.me,2008:Post/89
2013-01-11T23:16:00Z
2013-01-11T23:16:07Z
Ruby: fastest way of converting string into array of characters
<table class="t1">
<tr><th>time<th>code<th>comment<br />
<tr style="color:gray"><td> 0.147 <td> <code>s.bytes.to_a</code><td>most fastest, but returns <span class="caps">ASCII</span> codes instead of chars<br />
<tr style="background:#6f6"><td> 0.242 <td> <code>s.chars.to_a</code> <td><span class="caps">FASTEST</span><br />
<tr><td> 0.257 <td> <code>Array(s.chars)</code><br />
<tr><td> 0.265 <td> <code>a=[]; s.size.times{ |i| a<<s[i] }</code> <td><br />
<tr><td> 0.268 <td> <code>a=[]; s.chars.each{ |c| a<<c }</code> <td><br />
<tr><td> 0.278 <td> <code>s.bytes.map(&:chr)</code> <td><br />
<tr><td> 0.513 <td> <code>s.scan(/./)</code> <td><br />
<tr><td> 0.775 <td> <code>s.split(//)</code> <td><br />
<tr style="background:#f66"><td> 0.795 <td> <code>s.split('')</code> <td><span class="caps">SLOWEST</span></table>
<p>first column is time of 100.000 iterations on Core i5 1.7GHz</p>
<p>code: <a href="https://gist.github.com/4514850">bench-split.rb</a></p>
tag:zed.0xff.me,2008:Post/88
2012-12-27T13:03:00Z
2012-12-27T13:03:49Z
bReader - Читалка цитатников, которая экономит ваше время и трафик
<p><a href="https://play.google.com/store/apps/details?id=me.zed_0xff.android.breader"><img src="http://habrastorage.org/storage2/f0e/4b7/aa5/f0e4b7aa53716b9674068c0a7258ca34.jpg"/></a></p>
<h4>Особенные уникальности:</h4>
<ul>
<li>Поддержка картинок (xkcd, bash, что-то еще)</li>
<li>Цитаты обновляются через выделенный сервер обновлений, что: <br />
<ul><br />
<li>гораздо быстрее, чем парсить <span class="caps">HTML</span>/<span class="caps">XML</span> на устройстве</li>
<li>экономит трафик, сжимая его и не загружая повторно то, что уже загружено</li>
<li>ВСЕ цитатники обновляются одним запросом, 2-3 секунды – и у вас уже 200 новых цитат</li>
<p></ul></li><br />
<li>Все цитаты образуют единую ленту, но при желании можно читать любой цитатник отдельно.</li><br />
<li>Интеграция с твиттером (ну как без него) + все урлы жмутся через bit.ly, так что в один твит влезет больше полезного текста.</li><br />
<li>Читалка изначально заряжена 512-ю цитатами, так что даже в глуши без Интернета будет что почитать.</li></p>
</ul>
<h4>Изначально решил писать свою читалку потому что:</h4>
<ol>
<li>надоело ждать когда уже одна небезызвестная читалка распарсит все свои источники</li>
<li>при этом она еще и модальным окном загрузки все закрывает, хотя можно было бы и дать юзеру почитать то что есть, пока новое грузится</li>
<li>в случае зависания сети/сайта/хз чего – висла вся программа, целиком и полностью</li>
<li>некоторые цитатники (sramu.net) в <span class="caps">RSS</span> и на главной цитаты отдают не целиком, а половинку со ссылкой “читать дальше” – хотелось все-таки такие цитатники тоже читать нормально и без лишних кликов</li>
<li>ну и комиксы тоже интересно было чтоб были</li>
</ol>
<h4>Немного технических фактов</h4>
<ul>
<li>итого на написание ушло полгода</li>
<li>сам читаю цитатники каждый день</li>
<li>AppStore аналогичное мое приложение отклонил, сволочь</li>
<li>backend: nginx, ruby, Sinatra, memcached</li>
<li>хостинг: Amazon EC2 small instance</li>
<li><span class="caps">IDE</span>: <span class="caps">VIM</span>, rake</li>
</ul>
<habracut text="Список цитатников, больше скриншотов и ссылка на бесплатное скачивание"/>
<h4>Все цитатники: (38шт)</h4><table><tr><th><span class="caps">QDB</span></th><td>bash.org (English)</td></tr>
<tr><th>bash.altlinux.org</th><td><span class="caps">ALT</span> Linux Fortunator</td></tr>
<tr><th>bash.org.by</th><td>Цитатник Байнета</td></tr>
<tr><th>bash.org.ru</th><td>Цитатник Рунета</td></tr>
<tr><th>bash.org.ru комикс</th><td>комиксы по мотивам цитат</td></tr>
<tr><th>besit2.ru</th><td>если накипело…</td></tr>
<tr><th>bezdna.su</th><td>Лучшие цитаты из Бездны</td></tr>
<tr><th>comicsbook.ru</th><td>FFFuuu, trollface, forever alone, okay и другие комиксы.</td></tr>
<tr><th>delonevtebe.ru</th><td>Дело не в тебе | Неудачные свидания</td></tr>
<tr><th>det.org.ru</th><td>говорят дети</td></tr>
<tr><th>greatwords.ru</th><td>Великие слова — цитаты, афоризмы, высказывания</td></tr>
<tr><th>hatewall.ru</th><td>стена ненависти</td></tr>
<tr><th>ibash.org.ru</th><td>Новый цитатник Рунета</td></tr>
<tr><th>inwebwetrust комикс</th><td>Комиксы об Интернете</td></tr>
<tr><th>ipfw.ru</th><td>Цитатник канала #FreeBSD@RusNET</td></tr>
<tr><th>ithappens.ru</th><td>Клиент и саппорт. Разработчик и заказчик. Программист и программа.</td></tr>
<tr><th>killmepls.ru</th><td>Килл Ми Плз: Жизнь. Вид сзади.</td></tr>
<tr><th>kstatida.ru</th><td>Короткие полезные советы, основанные на личном жизненном опыте, иногда печальном.</td></tr>
<tr><th>la2bash.ru</th><td>Lineage 2 беседка</td></tr>
<tr><th>lorquotes.ru</th><td>Latest fortunes from Linux.Org.Ru.</td></tr>
<tr><th>nefart.ru</th><td>Вот такой не фарт!</td></tr>
<tr><th>nextjoke.net</th><td>Самые смешные шутки</td></tr>
<tr><th>pinator.org</th><td>Краткие мотивирующие высказывания</td></tr>
<tr><th>pip.ec</th><td>Сегодня был ППЦ</td></tr>
<tr><th>polniyp.me</th><td>Полный П!</td></tr>
<tr><th>psyhumor.ru</th><td>Психологи шутят</td></tr>
<tr><th>shortiki.com</th><td>короткие и смешные</td></tr>
<tr><th>sramu.net</th><td>постыдные истории, рассказанные реальными людьми</td></tr>
<tr><th>ukrbash.org</th><td>УкрБаш — український цитатник</td></tr>
<tr><th>wgbash.org</th><td>World of Tanks</td></tr>
<tr><th>wumocomicstrip.com</th><td>Wumo by Wulff & Morgenthaler – a commentary on life</td></tr>
<tr><th>xkcd.com</th><td>A webcomic of romance, sarcasm, math, and language.</td></tr>
<tr><th>xkcd.ru</th><td>xkcd по-русски</td></tr>
<tr><th>zadolba.li</th><td>задолба!ли</td></tr>
<tr><th>жж ellustrator</th><td>ЖЖ: Картинки здесь!</td></tr>
<tr><th>жж pirozhki-ru</th><td>ЖЖ: Пирожковая</td></tr>
<tr><th>жж poroshki</th><td>ЖЖ: Порошки: кристаллизованная поэзия</td></tr>
<tr><th>жж ru-comicstrip</th><td>ЖЖ: комиксы на русском</td></tr>
</table>
<h4>Скриншотики</h4>
<p><a href="http://photobucket.0xff.me/albums/v624/photozed/android/device-2012-12-14-212237_zps6193d634.png" target="_blank"><img src="http://photobucket.0xff.me/albums/v624/photozed/android/th_device-2012-12-14-212237_zps6193d634.png" border="0" alt="Photobucket" ></a> <a href="http://photobucket.0xff.me/albums/v624/photozed/android/device-2012-12-14-211924_zps2b886680.png" target="_blank"><img src="http://photobucket.0xff.me/albums/v624/photozed/android/th_device-2012-12-14-211924_zps2b886680.png" border="0" alt="Photobucket" ></a> <a href="http://photobucket.0xff.me/albums/v624/photozed/android/device-2012-12-14-211602_zps3df65337.png" target="_blank"><img src="http://photobucket.0xff.me/albums/v624/photozed/android/th_device-2012-12-14-211602_zps3df65337.png" border="0" alt="Photobucket" ></a> <a href="http://photobucket.0xff.me/albums/v624/photozed/android/device-2012-12-14-211639_zps8107e940.png" target="_blank"><img src="http://photobucket.0xff.me/albums/v624/photozed/android/th_device-2012-12-14-211639_zps8107e940.png" border="0" alt="Photobucket" ></a> <a href="http://photobucket.0xff.me/albums/v624/photozed/android/device-2012-12-14-211528_zps7cd400ea.png" target="_blank"><img src="http://photobucket.0xff.me/albums/v624/photozed/android/th_device-2012-12-14-211528_zps7cd400ea.png" border="0" alt="Photobucket" ></a></p>
<h4>Скачать</h4>
<p><a href="https://play.google.com/store/apps/details?id=me.zed_0xff.android.breader">bReader в Google.Play</a></p>
tag:zed.0xff.me,2008:Post/87
2012-05-10T12:55:00Z
2012-05-10T12:55:09Z
grub2 simple hardware boot switch
<h3>1. take any old unused <span class="caps">USB</span> stick (any size, 16M is more than enough, mine was 128M)</h3>
<pre><code>#fdisk -l /dev/sdc
Disk /dev/sdc: 126 MB, 126353408 bytes
16 heads, 32 sectors/track, 482 cylinders, total 246784 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x59d30b2a
Device Boot Start End Blocks Id System
/dev/sdc1 * 32 246271 123120 83 Linux</code></pre>
<h3>2. <strong>[optional]</strong> format it to ext2</h3>
<h3>3. find out its <span class="caps">UUID</span></h3>
<pre><code>#blkid /dev/sdc*
/dev/sdc1: UUID="3a5ef90f-0640-42c3-97c2-8743c822ba60" TYPE="ext2"
</code></pre>
<h3>4. do some simple grub2 scripting:</h3>
<pre><code>menuentry "auto" {
set foo_uuid=3a5ef90f-0640-42c3-97c2-8743c822ba60
set foo=empty
insmod part_gpt
insmod ext2
insmod search_fs_uuid
search --fs-uuid --no-floppy --set=foo $foo_uuid
if [ $foo = "empty" ]; then
# boot windows
insmod fat
insmod chain
search --fs-uuid --no-floppy --set=root B0D7-DA71
chainloader (${root})/efi/Microsoft/Boot/bootmgfw.efi
else
# boot linux
set root='(hd0,gpt1)'
search --no-floppy --fs-uuid --set=root 22c0603d-670e-4097-83d2-539b520fc75a
linux /boot/vmlinuz root=/dev/sda1
fi
}</code></pre>
<h3>So, if this (and exactly this, with unique <span class="caps">UUID</span>) <span class="caps">USB</span> stick is plugged in while computer boots – it will boot Linux, otherwise Windows will boot.</h3>
tag:zed.0xff.me,2008:Post/86
2012-04-02T17:20:00Z
2012-04-02T17:20:17Z
Dwarf Fortress
<p>Первая цивилизация погибла от (пары) <strong>злобных гоблинов</strong>.</p>
<p>Вторая тоже =).</p>
<p>Третья научилась строить <strong>ДВЕРЬ</strong>(!!!) на входе в поселение. Погибла от злобного тролля, который умел ломать двери.</p>
<p>Четвертая погибла от <strong>жажды</strong>. Потому что все речки и озера зимой замерзли, до подземных источников она докопаться не успела, а как из льда добыть воду не дотумкала.</p>
<p>Пятая сейчас погибает от.. <a href="http://dwarffortresswiki.org/index.php/DF2012:Release_information/0.34.07"><strong>обновления 34.07</strong></a>, после которого дети вдруг стали паниковать по поводу своей одежды (ее отсутствия или поношенности, а новую надевать не хотят) и сходить с ума..</p>
tag:zed.0xff.me,2008:Post/85
2012-01-17T13:03:00Z
2012-01-17T13:03:34Z
раскодируем Trojan.Siggen3.35000
<h2>лечение</h2>
<ul>
<li><a href="https://gist.github.com/1626577">декодер испорченных файлов</a> (<a href="https://gist.github.com/gists/1626577/download">прямая ссылка на скрипт</a>)</li>
<li><a href="http://rubyinstaller.org/">RubyInstaller для Windows</a></li>
</ul>
<h2>обнаружение</h2>
<p>Попался мне как-то в руки троянчик.<br />
Вот его анализ на <a href="http://pedump.me/2a8242105fed0d1708f56ae251c45e7e/">pedump.me</a><br />
Вот так он обнаруживается различными антивирусами:</p>
<table>
<tr>
<td> AntiVir: </td>
<td style="color:red;">TR/Offend.6610086.8 </td>
</tr>
<tr>
<td> BitDefender: </td>
<td style="color:red;">Trojan.Generic.6610086 </td>
</tr>
<tr>
<td> ClamAV: </td>
<td style="color:red;">Trojan.Dropper-31300 </td>
</tr>
<tr>
<td> DrWeb: </td>
<td style="color:red;">Trojan.Siggen3.35000 </td>
</tr>
<tr>
<td> Emsisoft: </td>
<td style="color:red;">Trojan.SuspectCRC!IK </td>
</tr>
<tr>
<td> F-Secure: </td>
<td style="color:red;">Trojan.Generic.6610086 </td>
</tr>
<tr>
<td> Fortinet: </td>
<td style="color:red;">W32/Filecoder.AA </td>
</tr>
<tr>
<td> GData: </td>
<td style="color:red;">Trojan.Generic.6610086 </td>
</tr>
<tr>
<td> Ikarus: </td>
<td style="color:red;">Trojan.SuspectCRC </td>
</tr>
<tr>
<td> K7AntiVirus: </td>
<td style="color:red;">Riskware </td>
</tr>
<tr>
<td> Kaspersky: </td>
<td style="color:red;"><span class="caps">UDS</span>:DangerousObject.Multi.Generic </td>
</tr>
<tr>
<td> McAfee: </td>
<td style="color:red;">Artemis!2A8242105FED </td>
</tr>
<tr>
<td> NOD32: </td>
<td style="color:red;">Win32/Filecoder.AA </td>
</tr>
<tr>
<td> Norman: </td>
<td style="color:red;">W32/Malware.<span class="caps">WVNX</span> </td>
</tr>
<tr>
<td> Panda: </td>
<td style="color:red;">Trj/CI.A </td>
</tr>
<tr>
<td> TheHacker: </td>
<td style="color:red;">Trojan/Filecoder.ab </td>
</tr>
</table>
<p><a href="https://www.virustotal.com/file/200c4a9de8f34ee08d1b9bd6e95e5cf7e0d761741d1c3143f9ea9d402d422ca1/analysis/1326698567/">полный отчет на virustotal.com</a></p>
<h2>анализ</h2>
<p>троян портит <span class="caps">JPG</span>, <span class="caps">DOC</span>, <span class="caps">XLS</span> файлы. Обнаружить испорченные файлы можно визуально по следующему куску данных в конце файла:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">001a2cfb: 34 36 34 36 34 34 33 38 34 36 34 36 34 35 33 31 |4646443846464531|<tt>
</tt>001a2d0b: 33 32 33 35 34 36 34 36 34 36 34 36 33 30 33 31 |3235464646463031|<tt>
</tt>001a2d1b: 33 30 33 30 33 30 33 30 33 30 33 30 33 30 33 30 |3030303030303030|<tt>
</tt>001a2d2b: 33 30 33 30 33 30 33 30 33 30 33 30 33 30 33 30 |3030303030303030|<tt>
</tt>001a2d3b: 33 30 33 30 33 30 33 30 33 30 33 30 33 30 33 30 |3030303030303030|<tt>
</tt>001a2d4b: 33 30 33 30 33 30 33 30 33 30 33 30 33 30 33 30 |3030303030303030|<tt>
</tt>001a2d5b: 33 30 33 30 14 00 00 00 00 fb 2c 1a 00 14 00 04 |3030......,.....|<tt>
</tt>001a2d6b: 00 00 0f 2d 1a 00 14 00 08 00 00 23 2d 1a 00 14 |...-.......#-...|<tt>
</tt>001a2d7b: 00 0c 00 00 37 2d 1a 00 14 00 10 00 00 4b 2d 1a |....7-.......K-.|<tt>
</tt>001a2d8b: 00 05 <tt>
</tt></pre></td>
</tr></table>
<p>(конкретные данные различны в зависимости от содержимого файла)</p>
<p>результат бинарного сравнения нормального (слева) и испорченного (справа) файла:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">00000000: ff 54<tt>
</tt>00000001: d8 2f<tt>
</tt>00000002: ff 54<tt>
</tt>00000003: e1 38<tt>
</tt>00000004: 25 7a<tt>
</tt>00000400: ff 54<tt>
</tt>00000401: ff 56<tt>
</tt>00000402: 01 56<tt>
</tt>00000403: 00 57<tt>
</tt>00000404: 00 55<tt>
</tt>00000800: 00 54<tt>
</tt>00000801: 00 51<tt>
</tt>00000802: 00 54<tt>
</tt>00000803: 00 51<tt>
</tt>00000804: 00 54<tt>
</tt>00000c00: 00 54<tt>
</tt>00000c01: 00 51<tt>
</tt>00000c02: 00 54<tt>
</tt>00000c03: 00 51<tt>
</tt>00000c04: 00 54<tt>
</tt>00001000: 00 54<tt>
</tt>00001001: 00 51<tt>
</tt>00001002: 00 54<tt>
</tt>00001003: 00 51<tt>
</tt>00001004: 00 54<tt>
</tt><tt>
</tt>[!] 168_ok.jpg is 1715451 bytes long<tt>
</tt>[!] 168_bad.jpg is 1715597 bytes long<tt>
</tt></pre></td>
</tr></table>
<p>фактически троян портит по 5 байт в файле с интервалом в 1024 байта. но не просто портит, а записывает оригинал в конец испорченного файла. вот наглядный вид чего он там понаписал:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">001a2d5f: 14 00 00 00 00 fb 2c 1a 00 |......,..|<tt>
</tt>001a2d68: 14 00 04 00 00 0f 2d 1a 00 |......-..|<tt>
</tt>001a2d71: 14 00 08 00 00 23 2d 1a 00 |.....#-..|<tt>
</tt>001a2d7a: 14 00 0c 00 00 37 2d 1a 00 |.....7-..|<tt>
</tt>001a2d83: 14 00 10 00 00 4b 2d 1a 00 |.....K-..|<tt>
</tt>001a2d8c: 05 <tt>
</tt></pre></td>
</tr></table>
tag:zed.0xff.me,2008:Post/84
2011-10-24T16:43:00Z
2011-10-24T16:43:27Z
radare2 0.8.x unnecessary memory zeroing fix
<p><a href="http://radare.org/">radare2</a> <a href="http://radare.org/y/bugs.php?bugs&s=view&id=49">bug</a></p>
<p>the bug only appears when debugging 32-bit binary on a 64-bit host</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="line c">diff -r e96275c214b5 libr/io/p/io_ptrace.c</span><tt>
</tt><span class="line head"><span class="head">--- </span>a/libr/io/p/io_ptrace.c Mon Oct 24 04:35:42 2011 +0200</span><tt>
</tt><span class="line head"><span class="head">+++ </span>b/libr/io/p/io_ptrace.c Mon Oct 24 16:48:31 2011 +0300</span><tt>
</tt><span class="line chg"><span class="chg">@@</span> -34,9 +34,11 <span class="chg">@@</span></span><tt>
</tt><span class="c"> #if __OpenBSD__ || __KFBSD__</span><tt>
</tt><span class="c"> #define debug_read_raw(x,y) ptrace(PTRACE_PEEKTEXT, (pid_t)(x), (caddr_t)(y), 0)</span><tt>
</tt><span class="c"> #define debug_write_raw(x,y,z) ptrace(PTRACE_POKEDATA, (pid_t)(x), (caddr_t)(y), (int)(size_t)(z))</span><tt>
</tt><span class="line ins"><span class="ins">+</span>typedef int ptrace_word; // int ptrace(int request, pid_t pid, caddr_t addr, int data);</span><tt>
</tt><span class="c"> #else</span><tt>
</tt><span class="c"> #define debug_read_raw(x,y) ptrace(PTRACE_PEEKTEXT, x, y, 0)</span><tt>
</tt><span class="c"> #define debug_write_raw(x,y,z) ptrace(PTRACE_POKEDATA, x, y, z)</span><tt>
</tt><span class="line ins"><span class="ins">+</span>typedef void* ptrace_word; // long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);</span><tt>
</tt><span class="c"> #endif</span><tt>
</tt><span class="c"> </span><tt>
</tt><span class="c"> static int debug_os_read_at(int pid, ut32 *buf, int sz, ut64 addr) {</span><tt>
</tt><span class="line chg"><span class="chg">@@</span> -63,10 +65,11 <span class="chg">@@</span></span><tt>
</tt><span class="c"> }</span><tt>
</tt><span class="c"> </span><tt>
</tt><span class="c"> static int ptrace_write_at(int pid, const ut8 *pbuf, int sz, ut64 addr) {</span><tt>
</tt><span class="line del"><span class="del">-</span> ut32 *buf = (ut32*)pbuf;</span><tt>
</tt><span class="line del"><span class="del">-</span> ut32 words = sz / sizeof (ut32);</span><tt>
</tt><span class="line del"><span class="del">-</span> ut32 last = sz % sizeof (ut32);</span><tt>
</tt><span class="line del"><span class="del">-</span> ut32 x, lr, *at = (ut32*)(size_t)addr;</span><tt>
</tt><span class="line ins"><span class="ins">+</span> ptrace_word *buf = (ptrace_word*)pbuf;</span><tt>
</tt><span class="line ins"><span class="ins">+</span> ut32 words = sz / sizeof (ptrace_word);</span><tt>
</tt><span class="line ins"><span class="ins">+</span> ut32 last = sz % sizeof (ptrace_word);</span><tt>
</tt><span class="line ins"><span class="ins">+</span> ut32 x, *at = (ptrace_word*)(size_t)addr;</span><tt>
</tt><span class="line ins"><span class="ins">+</span> ptrace_word lr;</span><tt>
</tt><span class="c"> if (sz<1 || addr==UT64_MAX)</span><tt>
</tt><span class="c"> return -1;</span><tt>
</tt><span class="c"> for (x=0; x<words; x++)</span><tt>
</tt></pre></td>
</tr></table>
tag:zed.0xff.me,2008:Post/83
2011-10-13T20:08:00Z
2011-10-13T18:08:01Z
printing from OSX & iOS to Canon MF-4018 shared via WNDR3700
<h1>0. Reason for this all</h1>
<p><img src="http://mdata.yandex.net/i?path=b0914115153_img_id5396653333269105302.jpg" style="width:200px;float:left;" title="HP Photosmart 5510" alt="HP Photosmart 5510" /></p>
<p>Just bought an <strong>HP Photosmart 5510</strong> with wifi & ePrint and my MacBook Air found and installed it via wifi without the need of any drivers or anything.</p>
<p><img src="http://mdata.yandex.net/i?path=b0710105442_img_id1853200644329217696.jpg" style="float:right;" title="Canon MF4018" alt="Canon MF4018" /></p>
<p>But I also have older <strong>Canon MF4018</strong>, connected directly to <strong>WNDR3700</strong> via usb, and which I failed to set up for printing from my Macs via wifi.</p>
<h1 style="clear:both;">1. Drivers</h1>
<p><img src="http://mdata.yandex.net/i?path=b0402152750_img_id8036593573375676882.jpg" style="float:left;" title="Netgear WNDR3700" alt="Netgear WNDR3700" /></p>
<p>The main reason why I failed is Canon’s drivers for MF4018 (or MF4010, their printing functions are the same). They only have more or less usable drivers for Windows and Linux, closed-source and bad designed, with a lot of proprietary stuff.</p>
<p>There is a <a href="http://wiki.openwrt.org/doc/howto/p910nd.server">way to make your OpenWRT router act like a print server</a> for Windows & Linux clients, but it refuses to work with <span class="caps">OSX</span> client.</p>
<p>And even if we’ll somehow force it to work with <span class="caps">OSX</span> client, it will still need a lot of Canon drivers installed on Mac and carefully configured. And definitely <strong>will not work with iOS</strong></p>
<h1 style="clear:both;">2. Workaround</h1>
<p>You can use one simple workaround if you have an <code>x86</code> or <code>x86_64</code> computer running 24/7 at your place. Or if you want to manually turn it on every time when you need to print something.</p>
<p>You can then install <a href="http://www.cups.org/"><span class="caps">CUPS</span></a> on your device, or use a Windows Printer Sharing.</p>
<p>Unacceptable for me. I only have <strong>WNDR3700</strong> on <code>ar71xx</code> platform, and <strong>AppleTV2</strong> on <code>ARM Cortex A8</code> running nearly 24/7 at my home.</p>
<h1>3. An Insight</h1>
<h2>If I can’t run an x86 PC 24/7 at my place — who or what can stop me to run it somewhere on Internet?!</h2>
<p>(I already have a pair of servers on Internet, so let’s increase their load average a little :)</p>
<p><strong><span class="caps">IMPORTANT</span></strong>: You’ll need to have a Real IP address at your place, or some other way of receiving data from your Internet server, like a <a href="http://www.revsys.com/writings/quicktips/ssh-tunnel.html"><span class="caps">SSH</span> tunnel</a>.</p>
<h1>4. Step-by-step guide</h1>
<ol>
<li>WNDR3700 (or other OpenWrt-based router, or DD-<span class="caps">WRT</span> one, or <a href="http://code.google.com/p/wl500g/">wl500g</a>)
<ol>
<li>Connect MF4018 via usb</li>
<li><a href="http://wiki.openwrt.org/doc/howto/p910nd.server">Set up p910nd</a></li>
<li>Open port 9100 in firewall:<br/><code>iptables -A INPUT -j ACCEPT -p tcp -s your.internet.server.real.ip --dport 9100</code></li>
</ol></li>
<li>Internet server
<ol>
<li>install <a href="http://www.cups.org/"><span class="caps">CUPS</span></a></li>
<li>install Canon Proprietary drivers: for example <a href="http://www.canon-europe.com/Support/Consumer_Products/products/Fax__Multifunctionals/Laser/LaserBase_MF_series/i-SENSYS_MF4010.aspx?DLtcmuri=tcm:13-823016&page=1&type=download"><span class="caps">UFRII</span>/<span class="caps">UFRII</span> LT Printer Driver for Linux v2.20</a></li>
<li>Add a printer:<br/><code>lpadmin -p mf4010 -P CNCUPSMF4010ZK.ppd -v socket://my.home.real.ip:9100 -o printer-is-shared=true</code></li>
<li>enable <span class="caps">CUPS</span> Internet sharing: <br/> <img src="http://photobucket.0xff.me/albums/v624/photozed/blog/cups20111013.png" alt="" /></li>
<li>set up <span class="caps">CUPS</span> and/or firewall to only allow connections from <span class="caps">YOUR</span> home/office network</li>
</ol></li>
<li><strong>Optional steps</strong>, needed only for seamless printer autoconfiguration for <span class="caps">OSX</span>/iOS devices
<ol>
<li>Configure
<ol>
<li>Internet server: use <a href="https://github.com/tjfontaine/airprint-generate">airprint-generate</a> to generate a <code>.service</code> file for your printer</li>
<li>edit generated file: add <code><host-name>my.internet.server.real.ip</host-name></code></li>
<li>WNDR3700: install <code>avahi-daemon</code>, feed it with previously generated file, start it</li>
</ol></li>
<li>Now in <span class="caps">OSX</span> “Add Printers” Dialog just click “<strong><code>+</code></strong>” and it should see your printer, iOS should see your printer when you’ll try to print some photo</li>
</ol></li>
</ol>
<p>my autogenerated & edited <code>mf4010.service</code> file:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="pp"><?xml version="1.0"?></span><tt>
</tt><span class="dt"><!DOCTYPE service-group SYSTEM "avahi-service.dtd"></span><tt>
</tt><span class="ta"><service-group></span><tt>
</tt> <span class="ta"><name</span> <span class="an">replace-wildcards</span>=<span class="s"><span class="dl">"</span><span class="k">yes</span><span class="dl">"</span></span><span class="ta">></span>Canon MF4018<span class="ta"></name></span><tt>
</tt> <span class="ta"><service></span><tt>
</tt> <span class="ta"><type></span>_ipp._tcp<span class="ta"></type></span><tt>
</tt> <span class="ta"><subtype></span>_universal._sub._ipp._tcp<span class="ta"></subtype></span><tt>
</tt> <span class="ta"><port></span>631<span class="ta"></port></span><tt>
</tt> <span class="ta"><host-name></span>my.internet.server.real.ip<span class="ta"></host-name></span> <span class="c"><!-- EDIT THIS --></span><tt>
</tt> <span class="ta"><txt-record></span>txtvers=1<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>qtotal=1<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>Transparent=T<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>URF=none<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>rp=printers/mf4010<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>note=laser<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>product=(GPL Ghostscript)<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>printer-state=3<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>printer-type=0x821484<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"><txt-record></span>pdl=application/octet-stream,application/pdf,application/postscript,image/gif,image/jpeg,image/png,image/tiff,text/html,text/plain,application/vnd.cups-banner,application/vnd.cups-postscript,application/vnd.cups-raw,application/vnd.hp-hpgl,image/x-bitmap<span class="ta"></txt-record></span><tt>
</tt> <span class="ta"></service></span><tt>
</tt><span class="ta"></service-group></span><tt>
</tt></pre></td>
</tr></table>
tag:zed.0xff.me,2008:Post/82
2011-09-21T17:38:00Z
2011-09-21T17:38:56Z
hack.lu 2011 CTF -- Unknown Planet -- writeup
<p>[ <a href="http://lobotomy.me">Lobotomy</a> ]</p>
<h1>0. original image file</h1>
<p><img src="https://github.com/zed-0xff/ctf/raw/master/2011.hacklu/200.unknown.planet+/0_8c4f14e28155a2c3cf4b2538c1e0958b.jpg" alt="" /></p>
<h1>1. analyzing image</h1>
<p>all JPEGs have special <span class="caps">EOF</span> marker <strong><code>FF D9</code></strong> and no data must be after this marker.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed<span class="iv">@zmac</span> <span class="i">200</span>.unknown.planet+]<span class="c">#irb -E binary</span><tt>
</tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">004</span> > data=<span class="co">File</span>.read <span class="s"><span class="dl">'</span><span class="k">0_8c4f14e28155a2c3cf4b2538c1e0958b.jpg</span><span class="dl">'</span></span>; data.size<tt>
</tt> => <span class="i">194420</span> <tt>
</tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">005</span> > data.split(<span class="s"><span class="dl">"</span><span class="ch">\xff</span><span class="ch">\xd9</span><span class="dl">"</span></span>).map(&<span class="sy">:size</span>)<tt>
</tt> => [<span class="i">192405</span>, <span class="i">2013</span>] <tt>
</tt></pre></td>
</tr></table>
<p>so, we can see that there’s <strong>2013</strong> spare bytes after <span class="caps">EOF</span> marker.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="co">File</span>.open(<span class="s"><span class="dl">'</span><span class="k">foo</span><span class="dl">'</span></span>,<span class="s"><span class="dl">'</span><span class="k">w</span><span class="dl">'</span></span>){ |f| f<< data.split(<span class="s"><span class="dl">"</span><span class="ch">\xff</span><span class="ch">\xd9</span><span class="dl">"</span></span>).last }<tt>
</tt> => <span class="c">#<File:foo (closed)> </span><tt>
</tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">007</span> > ^<span class="co">D</span><tt>
</tt><tt>
</tt>[zed<span class="iv">@zmac</span> <span class="i">200</span>.unknown.planet+]<span class="c">#file foo</span><tt>
</tt><span class="ke">foo</span>: <span class="co">Zip</span> archive data, at least v2.<span class="i">0</span> to extract<tt>
</tt></pre></td>
</tr></table>
<p><span class="caps">AHA</span>! It’s a zip! :)</p>
<h1>2. unzipping</h1><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed@zmac 200.unknown.planet+]#unzip foo <tt>
</tt>Archive: foo<tt>
</tt> inflating: 5IIUED7GheR <tt>
</tt> inflating: 6JXtwsTTh9k <tt>
</tt> inflating: 87F1s5POUJc <tt>
</tt> inflating: BPiIOASG_Z6 <tt>
</tt> inflating: nLPA8X0UJqf <tt>
</tt> inflating: rySOWi4fZkA <tt>
</tt> inflating: uvlSlG3Tgow <tt>
</tt> inflating: Uw105aD3qYh <tt>
</tt> inflating: Yui5oq58hlx <tt>
</tt><tt>
</tt><tt>
</tt>[zed@zmac 200.unknown.planet+]#ls -la<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 5IIUED7GheR<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 6JXtwsTTh9k<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 87F1s5POUJc<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 BPiIOASG_Z6<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 Uw105aD3qYh<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 Yui5oq58hlx<tt>
</tt>-rw-r--r--@ 1 zed staff 1324 Apr 25 16:45 nLPA8X0UJqf<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 rySOWi4fZkA<tt>
</tt>-rw-r--r--@ 1 zed staff 20000 Apr 25 16:45 uvlSlG3Tgow<tt>
</tt><tt>
</tt>[zed@zmac 200.unknown.planet+]#file *<tt>
</tt>5IIUED7GheR: data<tt>
</tt>6JXtwsTTh9k: data<tt>
</tt>87F1s5POUJc: 8086 relocatable (Microsoft)<tt>
</tt>BPiIOASG_Z6: data<tt>
</tt>Uw105aD3qYh: data<tt>
</tt>Yui5oq58hlx: data<tt>
</tt>nLPA8X0UJqf: 8086 relocatable (Microsoft)<tt>
</tt>rySOWi4fZkA: data<tt>
</tt>uvlSlG3Tgow: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, mono 8000 Hz<tt>
</tt></pre></td>
</tr></table>
<p>Looks like audio file, that was split in chunks of 20000 bytes each. <br />
<strong><code>uvlSlG3Tgow</code></strong> is a first chunk b/c it has a <span class="caps">RIFF</span> <span class="caps">WAVE</span> header.<br />
<strong><code>nLPA8X0UJqf</code></strong> is a last tail chunk b/c it’s size less than 20000.</p>
<h1>3. gluing waves</h1>
<p>importing files in Audacity (or any other sound editor) discovers that source file is supposed to be a <a href="http://en.wikipedia.org/wiki/Morse_code">Morse</a> – coded message. But we must find a correct order of chunks.<br />
So, morse code consists of <code>dots</code> and <code>dashes</code>. Each kind must have fixed length.<br />
We suppose that source file was generated programmatically, not recorder from line or mic. So, it’s timings must be perfect.<br />
Following tool helps to manually find a correct chunks order.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt>35<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="dt">#!/usr/bin/env ruby</span><tt>
</tt><span class="co">STDOUT</span>.sync = <span class="pc">true</span><tt>
</tt><tt>
</tt><span class="r">if</span> <span class="pc">ARGV</span>.size == <span class="i">0</span><tt>
</tt> raise <span class="s"><span class="dl">"</span><span class="k">gimme at least one chunk filename</span><span class="dl">"</span></span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt>b0 = <span class="s"><span class="dl">"</span><span class="ch">\x80</span><span class="dl">"</span></span>*<span class="i">8</span><tt>
</tt>b1 = <span class="s"><span class="dl">"</span><span class="ch">\x27</span><span class="ch">\x01</span><span class="ch">\x27</span><span class="ch">\x80</span><span class="ch">\xd9</span><span class="ch">\xff</span><span class="ch">\xd9</span><span class="ch">\x80</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt>data = <span class="pc">ARGV</span>.map{ |x| <span class="co">File</span>.read(x) }.join.force_encoding(<span class="s"><span class="dl">'</span><span class="k">binary</span><span class="dl">'</span></span>)<tt>
</tt><span class="r">if</span> data[<span class="i">0</span>,<span class="i">4</span>] == <span class="s"><span class="dl">'</span><span class="k">RIFF</span><span class="dl">'</span></span><tt>
</tt> data = data[<span class="i">44</span>..<span class="i">-1</span>]<tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="co">N</span>=<span class="i">120</span><tt>
</tt><tt>
</tt>b0 = b0*<span class="co">N</span><tt>
</tt>b1 = b1*<span class="co">N</span><tt>
</tt><tt>
</tt>r = <span class="s"><span class="dl">'</span><span class="dl">'</span></span><tt>
</tt><span class="i">0</span>.step(data.size-<span class="i">1</span>,b0.size) <span class="r">do</span> |i|<tt>
</tt> <span class="r">case</span> (d=data[i,b0.size])<tt>
</tt> <span class="r">when</span> b0<tt>
</tt> print <span class="s"><span class="dl">"</span><span class="k">.</span><span class="dl">"</span></span><tt>
</tt> r << <span class="s"><span class="dl">'</span><span class="k">0</span><span class="dl">'</span></span><tt>
</tt> <span class="r">when</span> b1<tt>
</tt> print <span class="s"><span class="dl">"</span><span class="k">#</span><span class="dl">"</span></span><tt>
</tt> r << <span class="s"><span class="dl">'</span><span class="k">1</span><span class="dl">'</span></span><tt>
</tt> <span class="r">else</span><tt>
</tt> raise <span class="s"><span class="dl">"</span><span class="k">SYNC ERROR</span><span class="dl">"</span></span> <span class="r">if</span> d.size == b0.size<tt>
</tt> raise <span class="s"><span class="dl">"</span><span class="k">NOT ENOUGH DATA </span><span class="il"><span class="idl">#{</span>d.size<span class="idl">}</span></span><span class="k">/</span><span class="il"><span class="idl">#{</span>b0.size<span class="idl">}</span></span><span class="dl">"</span></span><tt>
</tt> raise <span class="s"><span class="dl">"</span><span class="k">unknown </span><span class="il"><span class="idl">#{</span>d.size<span class="idl">}</span></span><span class="k"> (normal: </span><span class="il"><span class="idl">#{</span>b0.size<span class="idl">}</span></span><span class="k">) bytes of data </span><span class="il"><span class="idl">#{</span>d.split(<span class="s"><span class="dl">'</span><span class="dl">'</span></span>).map{|x| <span class="s"><span class="dl">"</span><span class="k">%02x </span><span class="dl">"</span></span> % x.ord}.join<span class="idl">}</span></span><span class="dl">"</span></span><tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>calling with a single chunk – script says that it needs more data (more chunks):</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed<span class="iv">@zmac</span> <span class="i">1</span>]<span class="c">#./2_manually_guess_chunk_order.rb uvlSlG3Tgow </span><tt>
</tt><span class="c">##..######..######.../2_manually_guess_chunk_order.rb:32:in `block in <main>': NOT ENOUGH DATA 756/960</span><tt>
</tt></pre></td>
</tr></table>
<p>calling with wrong 2nd chunk => <code>SYNC ERROR</code>:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed<span class="iv">@zmac</span> <span class="i">1</span>]<span class="c">#./2_manually_guess_chunk_order.rb uvlSlG3Tgow 6JXtwsTTh9k </span><tt>
</tt><span class="c">##..######..######..###./2_manually_guess_chunk_order.rb:31:in `block in <main>': SYNC ERROR </span><tt>
</tt></pre></td>
</tr></table>
<p>two chunks in correct order, script says it needs more chunks:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed<span class="iv">@zmac</span> <span class="i">1</span>]<span class="c">#./2_manually_guess_chunk_order.rb uvlSlG3Tgow 5IIUED7GheR </span><tt>
</tt><span class="c">##..######..######..##......##..##..##..#./2_manually_guess_chunk_order.rb:32:in `block in <main>': NOT ENOUGH DATA 596/960 </span><tt>
</tt></pre></td>
</tr></table>
<p>all chunks in correct order:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed<span class="iv">@zmac</span> <span class="i">1</span>]<span class="c">#./2_manually_guess_chunk_order.rb uvlSlG3Tgow 5IIUED7GheR rySOWi4fZkA 87F1s5POUJc 6JXtwsTTh9k Uw105aD3qYh BPiIOASG_Z6 Yui5oq58hlx nLPA8X0UJqf </span><tt>
</tt><span class="c">##..######..######..##......##..##..##..##......##......##..##......######..##..######......######..##..######..######......######..######..######......##..##..##......</span><tt>
</tt></pre></td>
</tr></table>
<h1>4. decoding Morse</h1>
<p>we’ll need a <a href="http://rubygems.org/gems/morse">ruby morse gem</a>. install it with “<strong><code>gem install morse</code></strong>”</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[zed<span class="iv">@zmac</span> <span class="i">200</span>.unknown.planet+]<span class="c">#irb</span><tt>
</tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">001</span> > r=<span class="s"><span class="dl">'</span><span class="k">##..######..######..##......##..##..##..##......##......##..##......######..##..######......######..##..######..######......######..######..######......##..##..##......</span><span class="dl">'</span></span><tt>
</tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">002</span> > require <span class="s"><span class="dl">'</span><span class="k">morse</span><span class="dl">'</span></span><tt>
</tt> => <span class="pc">true</span> <tt>
</tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">005</span> > puts <span class="co">Morse</span>.decode(r.gsub(<span class="s"><span class="dl">'</span><span class="k">......</span><span class="dl">'</span></span>,<span class="s"><span class="dl">"</span><span class="k"> </span><span class="dl">"</span></span>).gsub(<span class="s"><span class="dl">'</span><span class="k">######</span><span class="dl">'</span></span>,<span class="s"><span class="dl">'</span><span class="k">-</span><span class="dl">'</span></span>).gsub(<span class="s"><span class="dl">'</span><span class="k">.</span><span class="dl">'</span></span>,<span class="s"><span class="dl">'</span><span class="dl">'</span></span>).gsub(<span class="s"><span class="dl">'</span><span class="k">##</span><span class="dl">'</span></span>,<span class="s"><span class="dl">'</span><span class="k">.</span><span class="dl">'</span></span>))<tt>
</tt><span class="co">PHEIKYOS</span><tt>
</tt></pre></td>
</tr></table>
<p>Voila! “<strong>Pheikyos</strong>” is the answer. Case-sensitive.</p>
<p style="color:gray;">PS: all source & data files are available at my <a href="https://github.com/zed-0xff/ctf/tree/master/2011.hacklu/200.unknown.planet+" style="color:gray;">ctf github repo</a>.</p>
tag:zed.0xff.me,2008:Post/81
2011-09-15T09:58:00Z
2011-09-15T09:58:12Z
iphone glossy buttons howto
<h2>sample images</h2>
<table><tr align=center><td>one big sample image</td><td>33 individual button images</td><p></tr><tr><td><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/glossy-accept-buttons.png" alt="" /></p>
</td>
<td>
<p><img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR00.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG00.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB00.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR01.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG01.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB01.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR02.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG02.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB02.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR03.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG03.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB03.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR04.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG04.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB04.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR05.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG05.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB05.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR06.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG06.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB06.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR07.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG07.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB07.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR08.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG08.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB08.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR09.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG09.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB09.png" alt="" /><br />
<img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnR10.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnG10.png" alt="" /> <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB10.png" alt="" /></p>
<p></td></tr></table></p>
<h2>ObjC code</h2>
<p>Following ObjC code uses iphone Private <span class="caps">API</span> (<strong><code>UIGlassButton</code></strong> class), so it may be rejected from AppStore.<br />
<span class="caps">BUT</span> you can generate a lot of iphone-style glossy button images with it, save to <span class="caps">PNG</span>, and use in your projects.</p>
<p><strong><span class="caps">IMPORTANT</span>:</strong> this code must be run on <strong>iPhone simulator</strong>. it saves <span class="caps">PNG</span> images to <code>/tmp</code> folder on your computer</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="pp">#define</span> UIColorFromRGBA(rgbValue,a) [UIColor colorWithRed:((<span class="pt">float</span>)((rgbValue & <span class="hx">0xFF0000</span>) >> <span class="i">16</span>))/<span class="i">25</span><span class="fl">5</span><span class="fl">.0</span> \<tt>
</tt> green:((<span class="pt">float</span>)((rgbValue & <span class="hx">0xFF00</span>) >> <span class="i">8</span>))/<span class="i">25</span><span class="fl">5</span><span class="fl">.0</span> \<tt>
</tt> blue:((<span class="pt">float</span>)(rgbValue & <span class="hx">0xFF</span>))/<span class="i">25</span><span class="fl">5</span><span class="fl">.0</span> alpha:a]<tt>
</tt><tt>
</tt>Class theClass = NSClassFromString(<span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">UIGlassButton</span><span class="dl">"</span></span>);<tt>
</tt><tt>
</tt><span class="r">for</span>(<span class="pt">int</span> j=<span class="i">0</span>;j<<span class="i">3</span>;j++){<tt>
</tt> <span class="r">for</span>(<span class="pt">int</span> i=<span class="i">0</span>;i<=<span class="i">10</span>;i++){<tt>
</tt> UIButton *theButton = [[[theClass alloc] initWithFrame:CGRectMake(<span class="i">5</span>+<span class="i">120</span>*j, <span class="i">5</span>+i*<span class="i">44</span>, <span class="i">120</span>, <span class="i">44</span>)] autorelease];<tt>
</tt> [theButton setValue:UIColorFromRGBA(<span class="hx">0xff</span><<(j*<span class="i">8</span>),<span class="fl">0</span><span class="fl">.1</span>*i) forKey:<span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">tintColor</span><span class="dl">"</span></span>];<tt>
</tt> <span class="c">//[theButton setTitle:@"Accept" forState:UIControlStateNormal];</span><tt>
</tt> [self.view addSubview:theButton];<tt>
</tt> <tt>
</tt> UIGraphicsBeginImageContext(theButton.frame.size);<tt>
</tt> CGContextRef theContext = UIGraphicsGetCurrentContext();<tt>
</tt> [theButton.layer renderInContext:theContext];<tt>
</tt> <tt>
</tt> UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();<tt>
</tt> NSData *theData = UIImagePNGRepresentation(theImage);<tt>
</tt> [theData writeToFile:[NSString stringWithFormat:<tt>
</tt> <span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">/tmp/btn%@%02i.png</span><span class="dl">"</span></span>,<tt>
</tt> j==<span class="i">0</span> ? <span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">B</span><span class="dl">"</span></span> : (j==<span class="i">1</span> ? <span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">G</span><span class="dl">"</span></span> : <span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">R</span><span class="dl">"</span></span>),<tt>
</tt> i] atomically:NO];<tt>
</tt> <tt>
</tt> UIGraphicsEndImageContext();<tt>
</tt> }<tt>
</tt>}<tt>
</tt></pre></td>
</tr></table>
<h2>and now make them stretch</h2>
<p>automatically stretching <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/btnB10.png" alt="" /> to <img src="http://photobucket.0xff.me/albums/v624/photozed/iphone/glossy-buttons/long-button.png" alt="" /><br />
<span style="color:gray">(oops, button lost a shadow during screen capture, not important here though)</span></p>
<p>note that <strong><code>stretchableImageWithLeftCapWidth</code></strong> method:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"> UIButton* button = [[UIButton alloc] init];<tt>
</tt> [button setTitle:<span class="er">@</span><span class="s"><span class="dl">"</span><span class="k"> looong long long very long text </span><span class="dl">"</span></span> forState:UIControlStateNormal];<tt>
</tt> [button setBackgroundImage:[[UIImage imageNamed:<span class="er">@</span><span class="s"><span class="dl">"</span><span class="k">btnB10.png</span><span class="dl">"</span></span>] stretchableImageWithLeftCapWidth:<span class="i">10</span> topCapHeight:<span class="i">10</span>] forState:UIControlStateNormal];<tt>
</tt> [button sizeToFit];<tt>
</tt></pre></td>
</tr></table>
<p><strong>NB:</strong> Don’t forget to <code>release</code> a <code>button</code> ! :)</p>
tag:zed.0xff.me,2008:Post/80
2011-09-04T07:19:00Z
2011-09-04T06:44:58Z
Наноисследование твиттера :)
<h2>1. Очевидный факт – минимальная длина юзернейма в твиттере = 1 символ</h2>
<p>примеры: <a href="http://twitter.com/#!/a">@a</a> <a href="http://twitter.com/#!/b">@b</a> <a href="http://twitter.com/#!/0">@0</a><br />
естественно, на данный момент они уже все давно заняты :)</p>
<h2>2. Не всякий @lol это <span class="caps">LOL</span> и не всякий @nike это Nike</h2>
<p>примеры:</p>
<table class="t1">
<tr>
<td> <a href="http://twitter.com/#!/nike">@nike</a> </td>
<td style="text-align:right;"><strong>1K</strong> followers </td>
<td style="text-align:right;">0 tweets </td>
<td style="color:red;">ни разу не найк </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/adidas">@adidas</a> </td>
<td style="text-align:right;"><strong>4K</strong> followers </td>
<td style="text-align:right;">170 tweets </td>
<td> вроде как адидас </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/puma">@puma</a> </td>
<td style="text-align:right;"><strong>21K</strong> followers </td>
<td style="text-align:right;">1200 tweets </td>
<td> аутентичная пума </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/sela">@sela</a> </td>
<td style="text-align:right;">46 followers </td>
<td style="text-align:right;">4 tweets </td>
<td style="color:red;">какой-то мужик </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/mcdonalds">@mcdonalds</a> </td>
<td style="text-align:right;"><strong>163K</strong> followers </td>
<td style="text-align:right;">5500 tweets </td>
<td> аутентичный макдак </td>
</tr>
<tr>
<td colspan="4"> </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/lol">@lol</a> </td>
<td style="text-align:right;">800 followers </td>
<td style="text-align:right;">41 tweets </td>
<td style="color:red;">совсем не смешно </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/humor">@humor</a> </td>
<td style="text-align:right;">1200 followers </td>
<td style="text-align:right;">13 tweets </td>
<td style="color:red;">аналогично </td>
</tr>
<tr>
<td colspan="4"> </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/yandex">@yandex</a> </td>
<td style="text-align:right;"><strong>65K</strong> followers </td>
<td style="text-align:right;">800 tweets </td>
<td> аутентичный яндекс </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/google">@google</a> </td>
<td style="text-align:right;"><strong>3.5M</strong> followers </td>
<td style="text-align:right;">2800 tweets </td>
<td> аутентичный гугл </td>
</tr>
<tr>
<td> <a href="http://twitter.com/#!/apple">@apple</a> </td>
<td style="text-align:right;"><strong>2K</strong> followers </td>
<td style="text-align:right;">2 tweets </td>
<td style="color:red;">не эппл ни разу </td>
</tr>
</table>
<h2>Вывод №1: популярный юзернейм вроде @apple или @humor может принести пару тысяч лишних фолловеров</h2>
<h2>Вывод №2: что следует сделать твиттеру</h2>
<p>Твиттеру следует сделать возможность покупки уже существующих имен. Не принудительной естественно. Просто при заходе в чужой профиль кнопочка “<strong>I want to buy this username</strong>” и как на ебее – ставки, минимальная цена, аукцион (опционально) и т.п.<br />
А может и сам владелец профиля у себя в настройках выставлять “<strong>I would sell this username for at least $5000</strong>”.<br />
Соответственно если кто-то на эту кнопочку нажал, и сумму указал, он подтверждает что он не просто так нажал, а этим взял на себя <strong>обязательство</strong> в <strong>случае согласия владельца юзернейма</strong> купить его (юзернейм, а не владельца :) за указанную сумму.</p>