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>Потом она позвонила, спросила куда я хочу &#8211; в Дублин или Цюрих? Я удивился, ибо про Цюрих не знал ни сном ни духом&#8230; Думал только в Дублин зовут.</p> <p>Еще сказала что у них есть Software Engineers, а есть Systems Engineers, короче техподдержка серверов и сервисов. Спросила меня куда я хочу, я сказал что не уверен. (но видимо мне таки ближе Systems Engineers :))</p> <p>Потом начались технические вопросы, порядка 20 штук, довольно элементарные, разделенные на разделы:</p> <ol> <li>админство *nix</li> <li>алгоритмы</li> <li>структуры данных</li> </ol> <p>Вопросы из разряда &#8220;что такое inode&#8221;, &#8220;сколько бит занимают права владельца файла в <span class="caps">UNIX</span> <span class="caps">ACL</span>&#8221;, &#8220;оцените время выполнения qsearch в worst case случае&#8221; (на последний я не ответил, ибо во всяких этих ваших 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 /> Какого хрена делал карбюратор на самолете&#8230; ума не приложу, вот так вот исторически сложилось.<br /> Это я еще молчу о том что когда я пришел на этот самолет, тут турбины вообще крутили специально обученные белки! O_O Воняяяялооооо&#8230;. Бо́льшая часть багажного отсека была забита кормом для белок. Они еще и дохли периодически, а другие размножались. Приходилось как-то поддерживать баланс рождаемости-смертности белок, утилизировать их какашки и тельца, следить за тем чтобы они не бегали по салону и не кусали пассажиров&#8230;<br /> Вобщем, инжектор &#8211; это просто манна небесная!</p> <p>Туалет в самолете просто класс! Очень просторный (0.5х0.5х1.5м) и многофункциональный (поддерживаются функции PP и KK). Есть один небольшой нюанс. С вероятностью 10% незадачливого пассажира намертво присасывает к той самой дырке(давлением 4.04 psi), а с другой стороны, с вероятностью те же 10% оттуда прямо на пассажира начинает фонтанировать давлением 5.05 psi все его ужасное содержимое&#8230;<br /> Но, как отметили 80% пассажиров: &#8220;у нас все получилось&#8221;, так что не ремонт туалета пока не заморачиваемся.<br /> Подавляющее большинство довольно &#8211; значит все у нас хорошо!!</p> <p>Авиакомпания у нас очень прибыльная. Потому что мы стремимся перевезти всех пассажиров, которые хотят лететь. Поэтому текущим ремонтом и даже усовершенствованием приходится заниматься в прямом смысле &#8220;на лету&#8221;.<br /> Хорошо что у нас есть команда бесстрашных инженеров-механиков. Но не всегда хорошо что бесстрашных.</p> <p>Например, инженер по приборам &#8211; очень толковый парень. Благодаря ему мы наконец-то можем в реальном времени видеть сколько у нас горючего в баках, заряд аккумуляторов, текущую скорость, и даже выпускать шасси!! (раньше шасси было как у &#8220;кукурузника&#8221; например)<br /> Так вот, недавно он приделал классную штуку, альтиметр называется. &#8220;Теперь мы можем всегда знать нашу высоту полета! А не спрашивать языком жестов пролетающие мимо борта&#8221; &#8211; подумали мы.<br /> Свежевключенный альтиметр показал высоту что-то около 56млн км над уровнем моря. O_O<br /> &#8211; Какого моря?!<br /> &#8211; <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>&#8230;<br /> &#8211; <code>#(*$&amp;^&amp;</code>#$(!!!!!<br /> Так и живем&#8230;</p> <p>Еще есть специалист по тонкой электронике. Может из волоска и батарейки приемник собрать. Телевизионный.<br /> Взялся он как-то радар ремонтировать (что-то слишком много НЛО последнее время стал показывать)<br /> Ремонтировал-ремонтировал. &#8220;Готово&#8221; &#8211; говорит.<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">&quot;</span><span class="k">@afunc$qxzcupi</span><span class="dl">&quot;</span></span><tt> </tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">&quot;</span><span class="k">@Forms@TApplication@SetTitle$qqrx17System@AnsiString</span><span class="dl">&quot;</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">&quot;</span><span class="k">??3@YAXPAX@Z</span><span class="dl">&quot;</span></span><tt> </tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">&quot;</span><span class="k">?AFXSetTopLevelFrame@@YAXPAVCFrameWnd@@@Z</span><span class="dl">&quot;</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">&quot;</span><span class="k">@Forms@TApplication@SetTitle$qqrx17System@AnsiString</span><span class="dl">&quot;</span></span>, <span class="sy">:args</span> =&gt; <span class="pc">false</span><tt> </tt><tt> </tt><span class="c"># outputs &quot;Forms::TApplication::SetTitle&quot;</span><tt> </tt><tt> </tt>puts <span class="co">Unmangler</span>.unmangle <span class="s"><span class="dl">&quot;</span><span class="k">?AFXSetTopLevelFrame@@YAXPAVCFrameWnd@@@Z</span><span class="dl">&quot;</span></span>, <span class="sy">:args</span> =&gt; <span class="pc">false</span><tt> </tt><tt> </tt><span class="c"># outputs &quot;AFXSetTopLevelFrame&quot;</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' &quot;ok&quot;</span><span class="dl">)</span></span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">all `quotes` 'are' </span><span class="ch">\&quot;</span><span class="k">ok</span><span class="ch">\&quot;</span><span class="dl">&quot;</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> =&gt; <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> =&gt; [<span class="s"><span class="dl">&quot;</span><span class="k">abc</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="k">def</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="k">ghi</span><span class="dl">&quot;</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> =&gt; <span class="s"><span class="dl">&quot;</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">&quot;</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> =&gt; [<span class="s"><span class="dl">&quot;</span><span class="k">a</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="ch">\#</span><span class="k">{2+2}</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="k">b</span><span class="dl">&quot;</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> =&gt; [<span class="s"><span class="dl">&quot;</span><span class="k">a</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="k">4</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="k">b</span><span class="dl">&quot;</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> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">a </span><span class="ch">\#</span><span class="k">{2+2} b</span><span class="dl">&quot;</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> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">a 4 b</span><span class="dl">&quot;</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> =&gt; <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> =&gt; [<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> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">a 4 b</span><span class="dl">&quot;</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 &#8220;breaking&#8221; 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&lt;&lt;s[i] }</code> <td><br /> <tr><td> 0.268 <td> <code>a=[]; s.chars.each{ |c| a&lt;&lt;c }</code> <td><br /> <tr><td> 0.278 <td> <code>s.bytes.map(&amp;: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 секунды &#8211; и у вас уже 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>в случае зависания сети/сайта/хз чего &#8211; висла вся программа, целиком и полностью</li> <li>некоторые цитатники (sramu.net) в <span class="caps">RSS</span> и на главной цитаты отдают не целиком, а половинку со ссылкой &#8220;читать дальше&#8221; &#8211; хотелось все-таки такие цитатники тоже читать нормально и без лишних кликов</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>если накипело&#8230;</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 &amp; Morgenthaler &#8211; 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 &#8211; 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&amp;s=view&amp;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&lt;1 || addr==UT64_MAX)</span><tt> </tt><span class="c"> return -1;</span><tt> </tt><span class="c"> for (x=0; x&lt;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 &amp; 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&#8217;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 &amp; Linux clients, but it refuses to work with <span class="caps">OSX</span> client.</p> <p>And even if we&#8217;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&#8217;t run an x86 PC 24/7 at my place &#8212; 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&#8217;s increase their load average a little :)</p> <p><strong><span class="caps">IMPORTANT</span></strong>: You&#8217;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&amp;page=1&amp;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>&lt;host-name&gt;my.internet.server.real.ip&lt;/host-name&gt;</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> &#8220;Add Printers&#8221; Dialog just click &#8220;<strong><code>+</code></strong>&#8221; and it should see your printer, iOS should see your printer when you&#8217;ll try to print some photo</li> </ol></li> </ol> <p>my autogenerated &amp; 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">&lt;?xml version=&quot;1.0&quot;?&gt;</span><tt> </tt><span class="dt">&lt;!DOCTYPE service-group SYSTEM &quot;avahi-service.dtd&quot;&gt;</span><tt> </tt><span class="ta">&lt;service-group&gt;</span><tt> </tt> <span class="ta">&lt;name</span> <span class="an">replace-wildcards</span>=<span class="s"><span class="dl">&quot;</span><span class="k">yes</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>Canon MF4018<span class="ta">&lt;/name&gt;</span><tt> </tt> <span class="ta">&lt;service&gt;</span><tt> </tt> <span class="ta">&lt;type&gt;</span>_ipp._tcp<span class="ta">&lt;/type&gt;</span><tt> </tt> <span class="ta">&lt;subtype&gt;</span>_universal._sub._ipp._tcp<span class="ta">&lt;/subtype&gt;</span><tt> </tt> <span class="ta">&lt;port&gt;</span>631<span class="ta">&lt;/port&gt;</span><tt> </tt> <span class="ta">&lt;host-name&gt;</span>my.internet.server.real.ip<span class="ta">&lt;/host-name&gt;</span> <span class="c">&lt;!-- EDIT THIS --&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>txtvers=1<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>qtotal=1<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>Transparent=T<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>URF=none<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>rp=printers/mf4010<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>note=laser<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>product=(GPL Ghostscript)<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>printer-state=3<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</span>printer-type=0x821484<span class="ta">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;txt-record&gt;</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">&lt;/txt-record&gt;</span><tt> </tt> <span class="ta">&lt;/service&gt;</span><tt> </tt><span class="ta">&lt;/service-group&gt;</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> &gt; 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> =&gt; <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> &gt; data.split(<span class="s"><span class="dl">&quot;</span><span class="ch">\xff</span><span class="ch">\xd9</span><span class="dl">&quot;</span></span>).map(&amp;<span class="sy">:size</span>)<tt> </tt> =&gt; [<span class="i">192405</span>, <span class="i">2013</span>] <tt> </tt></pre></td> </tr></table> <p>so, we can see that there&#8217;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&lt;&lt; data.split(<span class="s"><span class="dl">&quot;</span><span class="ch">\xff</span><span class="ch">\xd9</span><span class="dl">&quot;</span></span>).last }<tt> </tt> =&gt; <span class="c">#&lt;File:foo (closed)&gt; </span><tt> </tt>ruby-<span class="fl">1.9</span>.<span class="i">2</span>-p290 :<span class="i">007</span> &gt; ^<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&#8217;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&#8217;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> &#8211; 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&#8217;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">&quot;</span><span class="k">gimme at least one chunk filename</span><span class="dl">&quot;</span></span><tt> </tt><span class="r">end</span><tt> </tt><tt> </tt>b0 = <span class="s"><span class="dl">&quot;</span><span class="ch">\x80</span><span class="dl">&quot;</span></span>*<span class="i">8</span><tt> </tt>b1 = <span class="s"><span class="dl">&quot;</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">&quot;</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">&quot;</span><span class="k">.</span><span class="dl">&quot;</span></span><tt> </tt> r &lt;&lt; <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">&quot;</span><span class="k">#</span><span class="dl">&quot;</span></span><tt> </tt> r &lt;&lt; <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">&quot;</span><span class="k">SYNC ERROR</span><span class="dl">&quot;</span></span> <span class="r">if</span> d.size == b0.size<tt> </tt> raise <span class="s"><span class="dl">&quot;</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">&quot;</span></span><tt> </tt> raise <span class="s"><span class="dl">&quot;</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">&quot;</span><span class="k">%02x </span><span class="dl">&quot;</span></span> % x.ord}.join<span class="idl">}</span></span><span class="dl">&quot;</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 &#8211; 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 &lt;main&gt;': NOT ENOUGH DATA 756/960</span><tt> </tt></pre></td> </tr></table> <p>calling with wrong 2nd chunk =&gt; <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 &lt;main&gt;': 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 &lt;main&gt;': 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&#8217;ll need a <a href="http://rubygems.org/gems/morse">ruby morse gem</a>. install it with &#8220;<strong><code>gem install morse</code></strong>&#8221;</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> &gt; 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> &gt; require <span class="s"><span class="dl">'</span><span class="k">morse</span><span class="dl">'</span></span><tt> </tt> =&gt; <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> &gt; 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">&quot;</span><span class="k"> </span><span class="dl">&quot;</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! &#8220;<strong>Pheikyos</strong>&#8221; is the answer. Case-sensitive.</p> <p style="color:gray;">PS: all source &amp; 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 &amp; <span class="hx">0xFF0000</span>) &gt;&gt; <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 &amp; <span class="hx">0xFF00</span>) &gt;&gt; <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 &amp; <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">&quot;</span><span class="k">UIGlassButton</span><span class="dl">&quot;</span></span>);<tt> </tt><tt> </tt><span class="r">for</span>(<span class="pt">int</span> j=<span class="i">0</span>;j&lt;<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&lt;=<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>&lt;&lt;(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">&quot;</span><span class="k">tintColor</span><span class="dl">&quot;</span></span>];<tt> </tt> <span class="c">//[theButton setTitle:@&quot;Accept&quot; 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">&quot;</span><span class="k">/tmp/btn%@%02i.png</span><span class="dl">&quot;</span></span>,<tt> </tt> j==<span class="i">0</span> ? <span class="er">@</span><span class="s"><span class="dl">&quot;</span><span class="k">B</span><span class="dl">&quot;</span></span> : (j==<span class="i">1</span> ? <span class="er">@</span><span class="s"><span class="dl">&quot;</span><span class="k">G</span><span class="dl">&quot;</span></span> : <span class="er">@</span><span class="s"><span class="dl">&quot;</span><span class="k">R</span><span class="dl">&quot;</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">&quot;</span><span class="k"> looong long long very long text </span><span class="dl">&quot;</span></span> forState:UIControlStateNormal];<tt> </tt> [button setBackgroundImage:[[UIImage imageNamed:<span class="er">@</span><span class="s"><span class="dl">&quot;</span><span class="k">btnB10.png</span><span class="dl">&quot;</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&#8217;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. Очевидный факт &#8211; минимальная длина юзернейма в твиттере = 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">&nbsp; </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">&nbsp; </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>Твиттеру следует сделать возможность покупки уже существующих имен. Не принудительной естественно. Просто при заходе в чужой профиль кнопочка &#8220;<strong>I want to buy this username</strong>&#8221; и как на ебее &#8211; ставки, минимальная цена, аукцион (опционально) и т.п.<br /> А может и сам владелец профиля у себя в настройках выставлять &#8220;<strong>I would sell this username for at least $5000</strong>&#8221;.<br /> Соответственно если кто-то на эту кнопочку нажал, и сумму указал, он подтверждает что он не просто так нажал, а этим взял на себя <strong>обязательство</strong> в <strong>случае согласия владельца юзернейма</strong> купить его (юзернейм, а не владельца :) за указанную сумму.</p>