<?xml version="1.0"?>

<rss version="2.0">
 <channel>
  <title>Karel Kubat's Blogaria</title>
  <link>http://www.kubat.nl/pages/blogaria</link>
  <description>Karel Kubat's rants that can't be placed elsewhere</description>

     <item>
    <title>Who is leeching my Facebook</title>
    <link>http://www.kubat.nl/pages/blogaria/295#295</link>
    <pubDate>Wed, 24 Apr 13 21:36:47 +0200</pubDate>
    <description>
 Priceless.

<p/>
Some time ago I linked a funny message on my Facebook status;
concerning  a <a href="http://www.amazon.com/gp/product/B0047E0EII/"
		 target="_blank">totally useless banana slicer</a>,
with the (funny?) remark: Be sure to read the customer reviews,
priceless. The first review is right off the start one of the best:

<p/> <i>"For decades I have been trying to come up with an ideal way
  to slice a banana. "Use a knife!" they say. Well...my parole officer
  won't allow me to be around knives. "Shoot it with a gun!"
  Background check...HELLO! I had to resort to carefully attempt to
  slice those bananas with my bare hands. 99.9% of the time, I would
  get so frustrated that I just ended up squishing the fruit in my
  hands and throwing it against the wall in anger. Then, after a fit
  of banana-induced rage, my parole officer introduced me to this
  kitchen marvel and my life was changed. No longer consumed by
  seething anger and animosity towards thick-skinned yellow fruit, I
  was able to concentrate on my love of theatre and am writing a
  musical play about two lovers from rival gangs that just try to make
  it in the world. I think I'll call it South Side Story."</i>

<p/>
Guess what? I received an e-mail...
<br/>
<center>
  <img src="/bld/amazon-bananaslicer.png"/>
</center>

<br/>The list of slicers goes on an on...

<b>Has someone been leeching my Facebook posts? Marketing gone
  haywire? LOL!</b>

 
</description>
   </item>
   <item>
    <title>Time for a compact Coolpix</title>
    <link>http://www.kubat.nl/pages/blogaria/294#294</link>
    <pubDate>Wed, 24 Apr 13 21:36:47 +0200</pubDate>
    <description>
 <img src="/bld/coolpix/Coolpix.png" class="floatright"/> I just
recently got a Nikon Coolpix A compact camera. I have an older Nikon
D100 that I really love for the lenses and possibilities, but at times
it's just too big to lug around. So, enter the litte compact. Here is
my (p)review of it after having played around with it for a few days.
Questions/remarks? Feel free to mail me at
<a href="mailto:karel@kubat.nl">karel@kubat.nl</a>. 

<ul>
  <li> The camera is pretty light and compact, so it does what it
  should for me. </li>

  <li> It has a fixed focus lens, 18.5mm (which compares to 28mm
  analog) at f=2.8. </li>

  <li> The lens operates on autofocus or on manual. </li>

  <li> There is no optical viewfinder, just a (pretty large) display
  on the back. </li>

  <li> The controls are comfortingly Nikon-like, with the standard
  on/off switch and shutter button, presets for automatic or manual
  modes, ISO selection, what you have. </li>

  <li> It features a pretty hefty sensor, especially for a compact
  camera - the same sensor that's built into the D7000 DSLR that
  operates at 16 megapixels. 
		    
</ul>

As for first impressions, it's really a compact camera, but it offers
a ton of features for fiddling and tuning. One can tell that the
purpose of this camera is to provide a small compact for seasoned
amateurs. There are two programmable buttons and two programmable
exposure modes to suit your needs. One of these programmable buttons
is at the front of the camera, and I followed a tip to set it to
fixing focus. Works great: you move the camera to focus on what you
want, hit the front button, and then move the view finder to fix up
the photo composition. Another semi-pro thing is that you can set the
file format to RAW and not worry about loads of camera settings - you
can do your adjustments later.

<p/> For me the boon is that the resolution is great, the quality of
the optics is very good given that the lens is a fixed-focus, and the
light sensitivity is really OK; 2.8 works for me when you can crank up
the ISO value.

<p/> Some disadvantages? Of course nothing's perfect. But to be
honest, I didn't find any important ones yet. Still, a few remarks.
When you set the file format to RAW then you need Nikon's ViewNX2
software to convert the pictures to other formats. On the other hand,
if you don't like that, you can always set the file format to lossless
JPEG on the camera itself. Another thing is that walking around with
only an 18.5mm lens "feels naked" - but that's actually the purpose of
it all, to stop lugging around lenses..

<p/> Time for a few test shots! Below each picture below is a link
"original" that loads a large-format JPEG file.

<hr/> Here's a shot in a café. It was really pretty dark; I wanted to
test the autofocus under bad conditions and colors when on 'auto'.
Hence there's no post-processing involved on the computer. It was shot
at ISO 2500, f=2.8, 1/30sec. The second picture is a cutout of the
bar and the bottles to show how far you can "zoom in" during
postprocessing before pixelating the picture.

<center>
  <p/>
  <img src="/bld/coolpix/cafe.small.jpg"/>
  <br/>
  <a href="/bld/coolpix/cafe.big.jpg" target="_blank">Original</a>
  
  <p/>
  <img src="/bld/coolpix/cutout.small.jpg"/>
  <br/>
  <a href="/bld/coolpix/cutout.big.jpg" target="_blank">Original</a>
</center>

<hr/> The following shows how wide-angle the 18.5mm lens is. The top
pictures are unaltered; the bottom ones are post-processed for some
(mild) perspective correction. (I should've left more space around the
objects to allow for recropping... good lesson.)

<center>
  <table>
    <tr>
      <td align="center"> <img src="/bld/coolpix/tower1.small.jpg"/> </td>
      <td align="center"> <img src="/bld/coolpix/tower2.small.jpg"/> </td>
    </tr>
    <tr>
      <td align="center"> <a href="/bld/coolpix/tower1.big.jpg"
	      target="_blank">Original</a> </td>
      <td align="center"> <a href="/bld/coolpix/tower2.big.jpg"
      target="_blank">Original</a> </td>
    </tr>

    <tr>
      <td align="center"> <p/> </td>
      <td align="center"> <p/> </td>
    </tr>

    <tr>
      <td align="center"> <img src="/bld/coolpix/tower1.smallcorr.jpg"/> </td>
      <td align="center"> <img src="/bld/coolpix/tower2.smallcorr.jpg"/> </td>
    </tr>
    <tr>
      <td align="center"> <a href="/bld/coolpix/tower1.bigcorr.jpg"
	      target="_blank">Original</a> </td>
      <td align="center"> <a href="/bld/coolpix/tower2.bigcorr.jpg"
	      target="_blank">Original</a> </td>
    </tr>
  </table>
</center>

<hr/>
Finally a contrast test. Here's a see-through with shadows and bright
(sunny) daylight. The image was shot at ISO 100. The right picture is
post-processed, of course. I could have made the shadows way lighter
than here, but that's a matter of taste - I think it would look unnatural.

<center>
  <table>
    <tr>
      <td align="center"> <img src="/bld/coolpix/seethru.small.jpg"/> </td>
      <td align="center"> <img src="/bld/coolpix/seethru.smallpost.jpg"/> </td>
    </tr>
    <tr>
      <td align="center"> <a href="/bld/coolpix/seethru.big.jpg"
	      target="_blank">Original</td>
      <td align="center"> <a href="/bld/coolpix/seethru.bigpost.jpg"
	      target="_blank">Original</td>
    </tr>
  </table>
</center>
 
</description>
   </item>
   <item>
    <title>Selling my Peavey amp</title>
    <link>http://www.kubat.nl/pages/blogaria/293#293</link>
    <pubDate>Mon, 15 Apr 13 12:02:50 +0200</pubDate>
    <description>
 I'm getting rid of my Peavey Series 400 "Musician" amp. It's basically a bass amp but if needed you can put other instruments on it too. A guitar will go well, and even vocals.

<p/> It consists of two speaker units that you can stack into a tower or use one as monitor, one as PA. Then there's the amp part itself. It's a hefty thing and takes up some space, but hey, there's a bonus. This was actually my first amp that made the drummer cringe and ask me to turn down the volume ;-) Output is some 400W.

<p/> I'm asking 150 euro's if you come pick it up, or 175 if you want me to bring it within a reasonable distance. Interested? Drop me a note on <a href="mailto:karel@kubat.nl">karel@kubat.nl</a>.

<p/> Here are some pics.

<center>
  <img src="/bld/peavey/peavey01.jpg"/> <p/>
  <img src="/bld/peavey/peavey02.jpg"/> <p/>
  <img src="/bld/peavey/peavey03.jpg"/> <p/>
  <img src="/bld/peavey/peavey04.jpg"/> <p/>
</center>
 
</description>
   </item>
   <item>
    <title>encfs Helper Revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/292#292</link>
    <pubDate>Mon, 01 Apr 13 15:21:15 +0200</pubDate>
    <description>
 I wrote <a href="/pages/blogaria/160#160">previously</a>
about <b>encfs</b>. Since I started using it, I became a big fan - I
use it for all project-related work. For me, it has the advantage of
having project-related stuff in a project-related uniquely encrypted
directory. In contrast, most OS-level encryptions, such as File Fault,
will encrypt your entire home directory, but won't let you
differentiate within that directory. So encfs gives me more
flexibility.

<p/> Recently, I updated the helper script to use "public"
mounting (when root mounts an encrypted filesystem) and to locate the
true "encfs" binary, instead of expecting it in /opt/local/bin.

<p/>Here's the result. Use it if you like. The instructions are -as
before-, copy/paste it to a file <b>/usr/local/bin/encfs</b> or into
any other directory in your execution path. Just make sure that it's
invoked <i>before</i> the true "encfs" executable that you have lying
somewhere.

<p/>Feedback als always welcome...

<pre><font color="#707070">#!/usr/bin/env perl</font>

<font color="#0000aa">use</font> <font color="#0000fa">strict</font>;
<font color="#0000aa">use</font> <font color="#0000fa">Cwd</font> <font color="#ff1010"><i>'abs_path'</i></font>;

<font color="#707070"># [KK 2010-02-16] 1.00, first version</font>
<font color="#707070"># [KK 2013-03-28] 1.01 --public mounting added. Locating true encfs added.</font>
<font color="#707070">#			Directory argument may start with a dot.</font>
<font color="#707070"># [KK 2013-04-01] 1.02 Small bugfix</font>
<font color="#0000aa">my</font> $VER = <font color="#ff1010"><i>'1.02'</i></font>;

<font color="#707070"># Find the true encfs.</font>
<font color="#0000aa">my</font> $encfs = <font color="#0000aa">undef</font>;
<font color="#0000aa">my</font> $this_ino = (<font color="#0000aa">stat</font>($0))[1]
  <font color="#0000aa">or</font> <font color="#0000aa">die</font>(<font color="#ff1010"><i>"encfs: can't even stat myself: $!\n"</i></font>);
<font color="#0000aa">for</font> <font color="#0000aa">my</font> $p (<font color="#0000aa">split</font>(/:/, $ENV{<font color="#0000fa">PATH</font>})) {
    <font color="#0000aa">my</font> $that_ino = (<font color="#0000aa">stat</font>(<font color="#ff1010"><i>"$p/encfs"</i></font>))[1];
    <font color="#0000aa">if</font> ($that_ino != $this_ino <font color="#0000aa">and</font> -<font color="#0000fa">x</font> <font color="#ff1010"><i>"$p/encfs"</i></font>) {
        $encfs = <font color="#ff1010"><i>"$p/encfs"</i></font>;
        <font color="#0000aa">last</font>;
    }
}
<font color="#0000aa">die</font>(<font color="#ff1010"><i>"encfs: didn't find a true encfs executable\n"</i></font>)
  <font color="#0000aa">unless</font> ($encfs);

<font color="#0000aa">if</font> ($<font color="#707070">#ARGV == -1) {</font>
    <font color="#0000aa">print</font> <font color="#0000aa">STDERR</font> &lt;&lt;<font color="#ff1010"><i>"ENDUSAGE"</i></font>;

<font color="#0000fa">This</font> <font color="#0000fa">is</font> <font color="#0000fa">encfs</font> <font color="#0000fa">helper</font> $VER
<font color="#0000fa">Copyright</font> (<font color="#0000fa">c</font>) <font color="#0000fa">Karel</font> <font color="#0000fa">Kubat</font> &lt;<font color="#0000fa">karel</font>\@kubat.<font color="#0000fa">nl</font>&gt;. <font color="#0000fa">All</font> <font color="#0000fa">rights</font> <font color="#0000fa">reserved</font>, <font color="#0000fa">GPLV3</font> <font color="#0000fa">applies</font>.

<font color="#0000fa">Use</font> <font color="#0000fa">as</font> <font color="#0000fa">follows</font>:
- <font color="#0000fa">Create</font> <font color="#0000fa">two</font> <font color="#0000fa">directories</font> <font color="#0000fa">in</font> <font color="#0000fa">the</font> <font color="#0000fa">same</font> <font color="#0000fa">path</font>, <font color="#0000fa">DIR</font> <font color="#0000aa">and</font> .<font color="#0000fa">DIR</font> (<font color="#0000fa">one</font> <font color="#0000fa">with</font> <font color="#0000fa">a</font> <font color="#0000fa">leading</font>
  <font color="#0000fa">dot</font>)
- <font color="#0000fa">Use</font> <font color="#ff1010"><i>"encfs DIR"</i></font> <font color="#0000aa">or</font> <font color="#ff1010"><i>"encfs .DIR"</i></font> <font color="#0000fa">to</font> <font color="#0000fa">mount</font> <font color="#0000fa">DIR</font>,
  <font color="#0000fa">encrypted</font> <font color="#0000fa">files</font> <font color="#0000fa">will</font> <font color="#0000fa">go</font> <font color="#0000fa">into</font> .<font color="#0000fa">DIR</font>, <font color="#0000fa">viewable</font> <font color="#0000fa">files</font> <font color="#0000fa">will</font> <font color="#0000fa">be</font> <font color="#0000fa">in</font> <font color="#0000fa">DIR</font>
- <font color="#0000aa">use</font> <font color="#ff1010"><i>"umount DIR"</i></font> <font color="#0000fa">to</font> <font color="#0000fa">unmount</font>
- <font color="#0000fa">If</font> <font color="#0000fa">you</font> <font color="#0000aa">do</font> <font color="#0000fa">this</font> <font color="#0000fa">as</font> <font color="#0000fa">root</font>, <font color="#0000fa">then</font> <font color="#0000fa">DIR</font> <font color="#0000fa">will</font> <font color="#0000fa">be</font> <font color="#0000fa">accessible</font> <font color="#0000aa">for</font> <font color="#0000fa">all</font> <font color="#0000fa">users</font> <font color="#0000fa">on</font> <font color="#0000fa">the</font>
  <font color="#0000aa">system</font>, <font color="#0000fa">otherwise</font> <font color="#0000fa">DIR</font> <font color="#0000fa">will</font> <font color="#0000fa">be</font> <font color="#0000fa">private</font> <font color="#0000fa">to</font> <font color="#0000fa">one</font> <font color="#0000fa">user</font>

<font color="#0000fa">The</font> <font color="#0000fa">original</font> <font color="#0000fa">encfs</font> <font color="#0000fa">usage</font> <font color="#0000fa">information</font> <font color="#0000fa">follows</font>:

<font color="#0000fa">ENDUSAGE</font>
    <font color="#0000aa">system</font>($encfs);

    <font color="#0000aa">exit</font>(1);
}

<font color="#707070"># If the argument by chance is a directory starting with a dot, then</font>
<font color="#707070"># remove it - we depend on the non-dot dir present.</font>
<font color="#0000aa">if</font> (-<font color="#0000fa">d</font> $ARGV[0] <font color="#0000aa">and</font> $ARGV[0] =~ /^\..*/) {
    $ARGV[0] =~ <font color="#0000aa">s</font>{^\.}{};
}

<font color="#707070"># Smuggle in the dot-directory of encrypted files if not given.</font>
<font color="#0000aa">if</font> (-<font color="#0000fa">d</font> $ARGV[0] <font color="#0000aa">and</font> $<font color="#707070">#ARGV == 0) {</font>
    <font color="#0000aa">my</font> @parts = <font color="#0000aa">split</font>(<font color="#ff1010"><i>'/'</i></font>, $ARGV[0]);
    $parts[$<font color="#707070">#parts] = '.' . $parts[$#parts];</font>
    <font color="#0000aa">unshift</font>(@ARGV, <font color="#0000aa">join</font>(<font color="#ff1010"><i>'/'</i></font>, @parts));
}

<font color="#707070"># Convert all args to absolute paths.</font>
<font color="#0000aa">my</font> @args = ( $encfs );
<font color="#0000aa">if</font> ($ENV{<font color="#0000fa">LOGNAME</font>} <font color="#0000aa">eq</font> <font color="#ff1010"><i>'root'</i></font>) {
    <font color="#0000aa">print</font>(<font color="#ff1010"><i>"Mounting in public mode (we're root).\n"</i></font>);
    <font color="#0000aa">push</font>(@args,<font color="#ff1010"><i>'--public'</i></font>);
} <font color="#0000aa">else</font> {
    <font color="#0000aa">print</font>(<font color="#ff1010"><i>"Mounting in private mode (non-root user).\n"</i></font>);
}

<font color="#0000aa">for</font> <font color="#0000aa">my</font> $a (@ARGV) {
    <font color="#0000aa">if</font> (-<font color="#0000fa">f</font> $a) {
        <font color="#0000aa">push</font>(@args, <font color="#0000fa">abs_path</font>($a));
    } <font color="#0000aa">elsif</font> (-<font color="#0000fa">d</font> $a) {
        <font color="#0000aa">push</font>(@args, <font color="#0000fa">abs_path</font>($a) . <font color="#ff1010"><i>'/'</i></font>);
    } <font color="#0000aa">else</font> {
        <font color="#0000aa">push</font>(@args, $a);
    }
}

<font color="#707070"># Exec true encfs</font>
<font color="#0000aa">print</font> (<font color="#ff1010"><i>"Running: @args\n"</i></font>);
<font color="#0000aa">exec</font>( {$encfs} @args );
<font color="#0000aa">die</font>(<font color="#ff1010"><i>"Failed to exec $encfs: $!\n"</i></font>);
</pre> 
</description>
   </item>
   <item>
    <title>c conf 1.17</title>
    <link>http://www.kubat.nl/pages/blogaria/291#291</link>
    <pubDate>Fri, 15 Mar 13 11:26:59 +0100</pubDate>
    <description>
 I just upped <a href="/pages/cconf">c-conf</a> to version 1.17; the
libs for Ubuntu x86/64 are now correctly found. Also my pet network
balancer <a href="http://crossroads.e-tunity.com">Crossroads</a> went
to version 2.80.
 
</description>
   </item>
   <item>
    <title>Flitsers op de Nederlandse wegen</title>
    <link>http://www.kubat.nl/pages/blogaria/290#290</link>
    <pubDate>Mon, 25 Feb 13 17:03:08 +0100</pubDate>
    <description>
 [Dutch] Voor gebruikers van mobieltjes: op <a href="http://www.kubat.nl/st" target="_blank">http://www.kubat.nl/st</a> vind je een handig lijstje, kort en beknopt, voor als je de auto instapt ;-)
 
</description>
   </item>
   <item>
    <title>OTG Revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/289#289</link>
    <pubDate>Mon, 14 Jan 13 17:24:53 +0100</pubDate>
    <description>
 I received a great report about parallel OTG cracking on a multinode
supercomputer. The information is also in <a href="/pages/otg">the OTG
  page</a>.

<p/> For your convenience, here is a direct link
to <a href="/otg/cracking_OTG_pub.pdf">the PDF report</a>. Licensing
information is contained within; basically, you can reproduce or
redistribute the work, as long as you credit the authors and don't use
it commercially. Enjoy!
 
</description>
   </item>
   <item>
    <title>Kalk revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/288#288</link>
    <pubDate>Fri, 11 Jan 13 09:52:33 +0100</pubDate>
    <description>
 The downloadable archive <a href="/pages/kalk">Kalk</a> is slightly
modified. The used library "getline" os now onboard in the archive, so
that Kalk should build on all systems (that have g++ installed).
 
</description>
   </item>
   <item>
    <title>God is coming</title>
    <link>http://www.kubat.nl/pages/blogaria/287#287</link>
    <pubDate>Wed, 12 Dec 12 14:15:39 +0100</pubDate>
    <description>
 A few days ago I was derping around on the <a href="http://cheezburger.com/4389748736
" target="_blank">Cheezburger network</a> when I saw the following picture:

<p/>
<center>
  <img src="/bld/GodIsComing1.png"/>
</center>

<p/>
This reminded me of something.. a picture of my own, and yes! After digging around a bit, here's a photo I shot in July 2008 in Scotland:

<p/>
<center>
  <img src="/bld/GodIsComing2.jpeg"/>
</center>

<p/>
What are the odds?! This is really the same wall, just look closely at the background. Also the "Cancelled" sticker is on exactly the same spot. At least two people had the same idea of "funny"... I remember that this was very close to a Japanese restaurant where we had dinner. As I enjoyed my soup with noodles I contemplated why God would be coming on CD, vinyl and download, but not iTunes or Spotify.
 
</description>
   </item>
   <item>
    <title>Strangely disturbing</title>
    <link>http://www.kubat.nl/pages/blogaria/286#286</link>
    <pubDate>Thu, 29 Nov 12 12:26:30 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/StrangelyDisturbing.gif"/>
</center>
 
</description>
   </item>
   <item>
    <title>How to sneeze on a motorbike</title>
    <link>http://www.kubat.nl/pages/blogaria/285#285</link>
    <pubDate>Tue, 27 Nov 12 16:37:23 +0100</pubDate>
    <description>
 I found that heavy sneezing while riding a motorbike can pose a significant problem. Sneezing with the visor down immediately reduces visibility due to sticky droplets on the inside of the formerly transparent perspex, while opening the visor and then sneezing isn't an option either when traveling at high speed or when it's cold outside. I think that I have now solved the problem using the below illustrated process. I plan to print this diagram, laminate it, and mount it above my handle bars for easy reference.

<p/>
<center>
  <img src="/bld/HowtoSneeze.png"/>
  <p/>
  Feedback as always welcome at
  <a href="mailto:karel@kubat.nl">karel@kubat.nl</a>.
</center>
 
</description>
   </item>
   <item>
    <title>Een aanslag uit de toekomst</title>
    <link>http://www.kubat.nl/pages/blogaria/284#284</link>
    <pubDate>Fri, 23 Nov 12 04:54:06 +0100</pubDate>
    <description>
 [Dutch] Ik heb wel eens van het antedateren van een brief gehoord. Maar <i>postdateren</i>? De Nederlandse Belastingdienst kan het. Ik kreeg een voorlopige aanslag teruggave voor volgend jaar (2013), door de accountant ontvangen op 21 november 2012 (zie stempel), met dagtekening.. jawel... 15 januari 2013. Is toch raar als je zo iets leest.

<p/>

<center>
  <img src="/bld/Belastingdienst-voorlopige-aanslag.png"/>
  <p/>
  (Grijze veegsels zijn door mij aangebracht. De rest is ongewijzigd.)
</center>

 
</description>
   </item>
   <item>
    <title>More voluntary layoffs</title>
    <link>http://www.kubat.nl/pages/blogaria/283#283</link>
    <pubDate>Thu, 22 Nov 12 06:20:53 +0100</pubDate>
    <description>
 A few months ago I wrote about a <a href="/pages/blogaria/264">voluntary layoff program at Societ&eacute; Generale going haywire</a>. They're not the only ones. Sharp has made the same mistake; they offered a nice early retirement package to its employees - but too many want it. I guess Sharp's workplace isn't that enticing. More at <a href="http://hardware.slashdot.org/story/12/11/20/162245/sharp-overwhelmed-by-volunteers-for-early-retirement" target="_blank">slashdot</a>.  
 
</description>
   </item>
   <item>
    <title>Browser fingerprint</title>
    <link>http://www.kubat.nl/pages/blogaria/282#282</link>
    <pubDate>Wed, 17 Oct 12 16:21:39 +0200</pubDate>
    <description>
 Just playing around. Your browser fingerprint is:
<pre id="fp_md5"></pre>

It originates from the following raw input (HTML-escaped and broken up into separate lines for readability):
<pre id="fp_raw"></pre>

For more info, visit
<ul>
  <li> <a href="http://arstechnica.com/tech-policy/news/2010/05/how-your-web-browser-rats-you-out-online.ars" target="_blank">Ars Technica</a>'s article on browser profiling; </li>
  <li> <a href="http://panopticlick.eff.org/"
	  target="_blank">panopticlick.eff.org</a>  </li>
  <li> .. and countless others. </li>
</ul>

If you want to play around with this yourself: here's the Javascript
code that gets you a browser fingerprint. Google jquery browser
fingerprinting to see Carlo Zottmann's original source for this. Other
credits go to Joseph Meyr for the Javascript md5 implementation. In
order to use this, call <i>fingerprint_md5()</i> to get the
fingerprint, or call <i>fingerprint_raw()</i> to get the full data
string from which the md5 hash is constructed.

<pre>
(<font color="#0000fa">function</font>() {
    <font color="#0000fa">function</font> <font color="#0000fa">md5cycle</font>(<font color="#0000fa">x</font>, <font color="#0000fa">k</font>) {
        <font color="#0000fa">var</font> <font color="#0000fa">a</font> = <font color="#0000fa">x</font>[0], <font color="#0000fa">b</font> = <font color="#0000fa">x</font>[1], <font color="#0000fa">c</font> = <font color="#0000fa">x</font>[2], <font color="#0000fa">d</font> = <font color="#0000fa">x</font>[3];

        <font color="#0000fa">a</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[0], 7, -680876936);
        <font color="#0000fa">d</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[1], 12, -389564586);
        <font color="#0000fa">c</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[2], 17, 606105819);
        <font color="#0000fa">b</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[3], 22, -1044525330);
        <font color="#0000fa">a</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[4], 7, -176418897);
        <font color="#0000fa">d</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[5], 12, 1200080426);
        <font color="#0000fa">c</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[6], 17, -1473231341);
        <font color="#0000fa">b</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[7], 22, -45705983);
        <font color="#0000fa">a</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[8], 7, 1770035416);
        <font color="#0000fa">d</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[9], 12, -1958414417);
        <font color="#0000fa">c</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[10], 17, -42063);
        <font color="#0000fa">b</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[11], 22, -1990404162);
        <font color="#0000fa">a</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[12], 7, 1804603682);
        <font color="#0000fa">d</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[13], 12, -40341101);
        <font color="#0000fa">c</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[14], 17, -1502002290);
        <font color="#0000fa">b</font> = <font color="#0000fa">ff</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[15], 22, 1236535329);

        <font color="#0000fa">a</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[1], 5, -165796510);
        <font color="#0000fa">d</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[6], 9, -1069501632);
        <font color="#0000fa">c</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[11], 14, 643717713);
        <font color="#0000fa">b</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[0], 20, -373897302);
        <font color="#0000fa">a</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[5], 5, -701558691);
        <font color="#0000fa">d</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[10], 9, 38016083);
        <font color="#0000fa">c</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[15], 14, -660478335);
        <font color="#0000fa">b</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[4], 20, -405537848);
        <font color="#0000fa">a</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[9], 5, 568446438);
        <font color="#0000fa">d</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[14], 9, -1019803690);
        <font color="#0000fa">c</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[3], 14, -187363961);
        <font color="#0000fa">b</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[8], 20, 1163531501);
        <font color="#0000fa">a</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[13], 5, -1444681467);
        <font color="#0000fa">d</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[2], 9, -51403784);
        <font color="#0000fa">c</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[7], 14, 1735328473);
        <font color="#0000fa">b</font> = <font color="#0000fa">gg</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[12], 20, -1926607734);

        <font color="#0000fa">a</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[5], 4, -378558);
        <font color="#0000fa">d</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[8], 11, -2022574463);
        <font color="#0000fa">c</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[11], 16, 1839030562);
        <font color="#0000fa">b</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[14], 23, -35309556);
        <font color="#0000fa">a</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[1], 4, -1530992060);
        <font color="#0000fa">d</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[4], 11, 1272893353);
        <font color="#0000fa">c</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[7], 16, -155497632);
        <font color="#0000fa">b</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[10], 23, -1094730640);
        <font color="#0000fa">a</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[13], 4, 681279174);
        <font color="#0000fa">d</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[0], 11, -358537222);
        <font color="#0000fa">c</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[3], 16, -722521979);
        <font color="#0000fa">b</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[6], 23, 76029189);
        <font color="#0000fa">a</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[9], 4, -640364487);
        <font color="#0000fa">d</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[12], 11, -421815835);
        <font color="#0000fa">c</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[15], 16, 530742520);
        <font color="#0000fa">b</font> = <font color="#0000fa">hh</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[2], 23, -995338651);

        <font color="#0000fa">a</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[0], 6, -198630844);
        <font color="#0000fa">d</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[7], 10, 1126891415);
        <font color="#0000fa">c</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[14], 15, -1416354905);
        <font color="#0000fa">b</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[5], 21, -57434055);
        <font color="#0000fa">a</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[12], 6, 1700485571);
        <font color="#0000fa">d</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[3], 10, -1894986606);
        <font color="#0000fa">c</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[10], 15, -1051523);
        <font color="#0000fa">b</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[1], 21, -2054922799);
        <font color="#0000fa">a</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[8], 6, 1873313359);
        <font color="#0000fa">d</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[15], 10, -30611744);
        <font color="#0000fa">c</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[6], 15, -1560198380);
        <font color="#0000fa">b</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[13], 21, 1309151649);
        <font color="#0000fa">a</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">k</font>[4], 6, -145523070);
        <font color="#0000fa">d</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">k</font>[11], 10, -1120210379);
        <font color="#0000fa">c</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">k</font>[2], 15, 718787259);
        <font color="#0000fa">b</font> = <font color="#0000fa">ii</font>(<font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">k</font>[9], 21, -343485551);

        <font color="#0000fa">x</font>[0] = <font color="#0000fa">add32</font>(<font color="#0000fa">a</font>, <font color="#0000fa">x</font>[0]);
        <font color="#0000fa">x</font>[1] = <font color="#0000fa">add32</font>(<font color="#0000fa">b</font>, <font color="#0000fa">x</font>[1]);
        <font color="#0000fa">x</font>[2] = <font color="#0000fa">add32</font>(<font color="#0000fa">c</font>, <font color="#0000fa">x</font>[2]);
        <font color="#0000fa">x</font>[3] = <font color="#0000fa">add32</font>(<font color="#0000fa">d</font>, <font color="#0000fa">x</font>[3]);
    }

    <font color="#0000fa">function</font> <font color="#0000fa">cmn</font>(<font color="#0000aa">q</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>) {
        <font color="#0000fa">a</font> = <font color="#0000fa">add32</font>(<font color="#0000fa">add32</font>(<font color="#0000fa">a</font>, <font color="#0000aa">q</font>), <font color="#0000fa">add32</font>(<font color="#0000fa">x</font>, <font color="#0000fa">t</font>));
        <font color="#0000aa">return</font> <font color="#0000fa">add32</font>((<font color="#0000fa">a</font> &lt;&lt; <font color="#0000aa">s</font>) | (<font color="#0000fa">a</font> &gt;&gt;&gt; (32 - <font color="#0000aa">s</font>)), <font color="#0000fa">b</font>);
    }

    <font color="#0000fa">function</font> <font color="#0000fa">ff</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>) {
        <font color="#0000aa">return</font> <font color="#0000fa">cmn</font>((<font color="#0000fa">b</font> &amp; <font color="#0000fa">c</font>) | ((~<font color="#0000fa">b</font>) &amp; <font color="#0000fa">d</font>), <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>);
    }

    <font color="#0000fa">function</font> <font color="#0000fa">gg</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>) {
        <font color="#0000aa">return</font> <font color="#0000fa">cmn</font>((<font color="#0000fa">b</font> &amp; <font color="#0000fa">d</font>) | (<font color="#0000fa">c</font> &amp; (~<font color="#0000fa">d</font>)), <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>);
    }

    <font color="#0000fa">function</font> <font color="#0000fa">hh</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>) {
        <font color="#0000aa">return</font> <font color="#0000fa">cmn</font>(<font color="#0000fa">b</font> ^ <font color="#0000fa">c</font> ^ <font color="#0000fa">d</font>, <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>);
    }

    <font color="#0000fa">function</font> <font color="#0000fa">ii</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">c</font>, <font color="#0000fa">d</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>) {
        <font color="#0000aa">return</font> <font color="#0000fa">cmn</font>(<font color="#0000fa">c</font> ^ (<font color="#0000fa">b</font> | (~<font color="#0000fa">d</font>)), <font color="#0000fa">a</font>, <font color="#0000fa">b</font>, <font color="#0000fa">x</font>, <font color="#0000aa">s</font>, <font color="#0000fa">t</font>);
    }

    <font color="#0000fa">function</font> <font color="#0000fa">md51</font>(<font color="#0000aa">s</font>) {
        // <font color="#0000fa">Converts</font> <font color="#0000fa">the</font> <font color="#0000fa">string</font> <font color="#0000fa">to</font> <font color="#0000fa">UTF</font>-8 <font color="#ff1010"><i>"bytes"</i></font> <font color="#0000fa">when</font> <font color="#0000fa">necessary</font>
        <font color="#0000aa">if</font> (/[\<font color="#0000fa">x80</font>-\<font color="#0000fa">xFF</font>]/.<font color="#0000fa">test</font>(<font color="#0000aa">s</font>)) {
            <font color="#0000aa">s</font> = <font color="#0000fa">unescape</font>(<font color="#0000fa">encodeURI</font>(<font color="#0000aa">s</font>));
        }
        <font color="#0000fa">txt</font> = <font color="#ff1010"><i>''</i></font>;
        <font color="#0000fa">var</font> <font color="#0000fa">n</font> = <font color="#0000aa">s</font>.<font color="#0000aa">length</font>, <font color="#0000aa">state</font> = [1732584193, -271733879,
                                   -1732584194, 271733878], <font color="#0000fa">i</font>;
        <font color="#0000aa">for</font> (<font color="#0000fa">i</font> = 64; <font color="#0000fa">i</font> &lt;= <font color="#0000aa">s</font>.<font color="#0000aa">length</font>; <font color="#0000fa">i</font> += 64) {
            <font color="#0000fa">md5cycle</font>(<font color="#0000aa">state</font>, <font color="#0000fa">md5blk</font>(<font color="#0000aa">s</font>.<font color="#0000fa">substring</font>(<font color="#0000fa">i</font> - 64, <font color="#0000fa">i</font>)));
        }
        <font color="#0000aa">s</font> = <font color="#0000aa">s</font>.<font color="#0000fa">substring</font>(<font color="#0000fa">i</font> - 64);
        <font color="#0000fa">var</font> <font color="#0000fa">tail</font> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        <font color="#0000aa">for</font> (<font color="#0000fa">i</font> = 0; <font color="#0000fa">i</font> &lt; <font color="#0000aa">s</font>.<font color="#0000aa">length</font>; <font color="#0000fa">i</font>++)
            <font color="#0000fa">tail</font>[<font color="#0000fa">i</font> &gt;&gt; 2] |= <font color="#0000aa">s</font>.<font color="#0000fa">charCodeAt</font>(<font color="#0000fa">i</font>) &lt;&lt; ((<font color="#0000fa">i</font> % 4) &lt;&lt; 3);
        <font color="#0000fa">tail</font>[<font color="#0000fa">i</font> &gt;&gt; 2] |= 0<font color="#0000fa">x80</font> &lt;&lt; ((<font color="#0000fa">i</font> % 4) &lt;&lt; 3);
        <font color="#0000aa">if</font> (<font color="#0000fa">i</font> &gt; 55) {
            <font color="#0000fa">md5cycle</font>(<font color="#0000aa">state</font>, <font color="#0000fa">tail</font>);
            <font color="#0000aa">for</font> (<font color="#0000fa">i</font> = 0; <font color="#0000fa">i</font> &lt; 16; <font color="#0000fa">i</font>++) <font color="#0000fa">tail</font>[<font color="#0000fa">i</font>] = 0;
        }
        <font color="#0000fa">tail</font>[14] = <font color="#0000fa">n</font> * 8;
        <font color="#0000fa">md5cycle</font>(<font color="#0000aa">state</font>, <font color="#0000fa">tail</font>);
        <font color="#0000aa">return</font> <font color="#0000aa">state</font>;
    }

    <font color="#0000fa">function</font> <font color="#0000fa">md5blk</font>(<font color="#0000aa">s</font>) {         /* <font color="#0000fa">I</font> <font color="#0000fa">figured</font> <font color="#0000fa">global</font> <font color="#0000fa">was</font> <font color="#0000fa">faster</font>.   */
        <font color="#0000fa">var</font> <font color="#0000fa">md5blks</font> = [], <font color="#0000fa">i</font>;     /* <font color="#0000fa">Andy</font> <font color="#0000fa">King</font> <font color="#0000fa">said</font> <font color="#0000aa">do</font> <font color="#0000fa">it</font> <font color="#0000fa">this</font> <font color="#0000fa">way</font>. */
        <font color="#0000aa">for</font> (<font color="#0000fa">i</font> = 0; <font color="#0000fa">i</font> &lt; 64; <font color="#0000fa">i</font> += 4) {
            <font color="#0000fa">md5blks</font>[<font color="#0000fa">i</font> &gt;&gt; 2] = <font color="#0000aa">s</font>.<font color="#0000fa">charCodeAt</font>(<font color="#0000fa">i</font>) +
                (<font color="#0000aa">s</font>.<font color="#0000fa">charCodeAt</font>(<font color="#0000fa">i</font> + 1) &lt;&lt; 8) +
                (<font color="#0000aa">s</font>.<font color="#0000fa">charCodeAt</font>(<font color="#0000fa">i</font> + 2) &lt;&lt; 16) +
                (<font color="#0000aa">s</font>.<font color="#0000fa">charCodeAt</font>(<font color="#0000fa">i</font> + 3) &lt;&lt; 24);
        }
        <font color="#0000aa">return</font> <font color="#0000fa">md5blks</font>;
    }

    <font color="#0000fa">var</font> <font color="#0000fa">hex_chr</font> = <font color="#ff1010"><i>'0123456789abcdef'</i></font>.<font color="#0000aa">split</font>(<font color="#ff1010"><i>''</i></font>);

    <font color="#0000fa">function</font> <font color="#0000fa">rhex</font>(<font color="#0000fa">n</font>) {
        <font color="#0000fa">var</font> <font color="#0000aa">s</font> = <font color="#ff1010"><i>''</i></font>, <font color="#0000fa">j</font> = 0;
        <font color="#0000aa">for</font> (; <font color="#0000fa">j</font> &lt; 4; <font color="#0000fa">j</font>++)
            <font color="#0000aa">s</font> += <font color="#0000fa">hex_chr</font>[(<font color="#0000fa">n</font> &gt;&gt; (<font color="#0000fa">j</font> * 8 + 4)) &amp; 0<font color="#0000fa">x0F</font>] +
            <font color="#0000fa">hex_chr</font>[(<font color="#0000fa">n</font> &gt;&gt; (<font color="#0000fa">j</font> * 8)) &amp; 0<font color="#0000fa">x0F</font>];
        <font color="#0000aa">return</font> <font color="#0000aa">s</font>;
    }

    <font color="#0000fa">function</font> <font color="#0000aa">hex</font>(<font color="#0000fa">x</font>) {
        <font color="#0000aa">for</font> (<font color="#0000fa">var</font> <font color="#0000fa">i</font> = 0; <font color="#0000fa">i</font> &lt; <font color="#0000fa">x</font>.<font color="#0000aa">length</font>; <font color="#0000fa">i</font>++)
            <font color="#0000fa">x</font>[<font color="#0000fa">i</font>] = <font color="#0000fa">rhex</font>(<font color="#0000fa">x</font>[<font color="#0000fa">i</font>]);
        <font color="#0000aa">return</font> <font color="#0000fa">x</font>.<font color="#0000aa">join</font>(<font color="#ff1010"><i>''</i></font>);
    }

    <font color="#0000fa">md5</font> = <font color="#0000fa">function</font> (<font color="#0000aa">s</font>) {
        <font color="#0000aa">return</font> <font color="#0000aa">hex</font>(<font color="#0000fa">md51</font>(<font color="#0000aa">s</font>));
    }

    /* <font color="#0000fa">this</font> <font color="#0000fa">function</font> <font color="#0000fa">is</font> <font color="#0000fa">much</font> <font color="#0000fa">faster</font>, <font color="#0000fa">so</font> <font color="#0000aa">if</font> <font color="#0000fa">possible</font> <font color="#0000fa">we</font> <font color="#0000aa">use</font> <font color="#0000fa">it</font>.
     * <font color="#0000fa">Some</font> <font color="#0000fa">IEs</font> <font color="#0000fa">are</font> <font color="#0000fa">the</font> <font color="#0000fa">only</font> <font color="#0000fa">ones</font> <font color="#0000fa">I</font> <font color="#0000fa">know</font> <font color="#0000fa">of</font> <font color="#0000fa">that</font> <font color="#0000fa">need</font> <font color="#0000fa">the</font> <font color="#0000fa">idiotic</font>
     * <font color="#0000fa">second</font> <font color="#0000fa">function</font>, <font color="#0000fa">generated</font> <font color="#0000fa">by</font> <font color="#0000fa">an</font> <font color="#0000aa">if</font> <font color="#0000fa">clause</font>.  */
    <font color="#0000fa">function</font> <font color="#0000fa">add32</font>(<font color="#0000fa">a</font>, <font color="#0000fa">b</font>) {
        <font color="#0000aa">return</font> (<font color="#0000fa">a</font> + <font color="#0000fa">b</font>) &amp; 0<font color="#0000fa">xFFFFFFFF</font>;
    }

    <font color="#0000aa">if</font> (<font color="#0000fa">md5</font>(<font color="#ff1010"><i>'hello'</i></font>) != <font color="#ff1010"><i>'5d41402abc4b2a76b9719d911017c592'</i></font>) {
        <font color="#0000fa">function</font> <font color="#0000fa">add32</font>(<font color="#0000fa">x</font>, <font color="#0000aa">y</font>) {
            <font color="#0000fa">var</font> <font color="#0000fa">lsw</font> = (<font color="#0000fa">x</font> &amp; 0<font color="#0000fa">xFFFF</font>) + (<font color="#0000aa">y</font> &amp; 0<font color="#0000fa">xFFFF</font>),
            <font color="#0000fa">msw</font> = (<font color="#0000fa">x</font> &gt;&gt; 16) + (<font color="#0000aa">y</font> &gt;&gt; 16) + (<font color="#0000fa">lsw</font> &gt;&gt; 16);
            <font color="#0000aa">return</font> (<font color="#0000fa">msw</font> &lt;&lt; 16) | (<font color="#0000fa">lsw</font> &amp; 0<font color="#0000fa">xFFFF</font>);
        }
    }
})();

<font color="#0000fa">function</font> <font color="#0000fa">fingerprint_raw</font>() {
    <font color="#0000aa">return</font> [
        <font color="#0000fa">navigator</font>.<font color="#0000fa">userAgent</font>,
        [ <font color="#0000fa">screen</font>.<font color="#0000fa">height</font>, <font color="#0000fa">screen</font>.<font color="#0000fa">width</font>, <font color="#0000fa">screen</font>.<font color="#0000fa">colorDepth</font> ].<font color="#0000aa">join</font>(<font color="#ff1010"><i>"x"</i></font>),
        ( <font color="#0000fa">new</font> <font color="#0000fa">Date</font>() ).<font color="#0000fa">getTimezoneOffset</font>(),
        !!<font color="#0000fa">window</font>.<font color="#0000fa">sessionStorage</font>,
        !!<font color="#0000fa">window</font>.<font color="#0000fa">localStorage</font>,
        $.<font color="#0000aa">map</font>( <font color="#0000fa">navigator</font>.<font color="#0000fa">plugins</font>, <font color="#0000fa">function</font>(<font color="#0000fa">p</font>) {
            <font color="#0000aa">return</font> [
                <font color="#0000fa">p</font>.<font color="#0000fa">name</font>,
                <font color="#0000fa">p</font>.<font color="#0000fa">description</font>,
                $.<font color="#0000aa">map</font>( <font color="#0000fa">p</font>, <font color="#0000fa">function</font>(<font color="#0000fa">mt</font>) {
                    <font color="#0000aa">return</font> [ <font color="#0000fa">mt</font>.<font color="#0000fa">type</font>, <font color="#0000fa">mt</font>.<font color="#0000fa">suffixes</font> ].<font color="#0000aa">join</font>(<font color="#ff1010"><i>"~"</i></font>);
                }).<font color="#0000aa">join</font>(<font color="#ff1010"><i>","</i></font>)
            ].<font color="#0000aa">join</font>(<font color="#ff1010"><i>"::"</i></font>);
        }).<font color="#0000aa">join</font>(<font color="#ff1010"><i>";"</i></font>)
    ].<font color="#0000aa">join</font>(<font color="#ff1010"><i>"###"</i></font>);
}

<font color="#0000fa">function</font> <font color="#0000fa">fingerprint_md5</font>() {
    <font color="#0000aa">return</font> <font color="#0000fa">md5</font>(<font color="#0000fa">fingerprint_raw</font>());
}
</pre>

<script type="text/javascript">
  function escapeHTML(string) {
    var pre = document.createElement('pre');
    var text = document.createTextNode( string );
    pre.appendChild(text);
    return pre.innerHTML;
  }

  var raw = escapeHTML(fingerprint_raw());
  var cont = '';
  while (raw.length > 80) {
      cont += raw.substring(0, 80);
      raw = raw.substring(80);
      cont += '\n';
  }
  if (raw.length)
      cont += raw;
  $("#fp_raw").html(cont);
  $("#fp_md5").html(fingerprint_md5());
</script>
 
</description>
   </item>
   <item>
    <title>Site layout revamped</title>
    <link>http://www.kubat.nl/pages/blogaria/281#281</link>
    <pubDate>Mon, 15 Oct 12 15:31:34 +0200</pubDate>
    <description>
 Yup, I somewhat revamped the site layout. That's the nice thing about sites that have organically evolved over the years (euphemism for homegrown stuff without a content management framework): you can fiddle endlessly with them.

<p/>
Anyway, I like it more than the previous style, which looked like the snapshot below.

<p/>
<center>
  <img src="/bld/site-before-revamp.png"/>
</center>
 
</description>
   </item>
   <item>
    <title>Crossroads performing well</title>
    <link>http://www.kubat.nl/pages/blogaria/280#280</link>
    <pubDate>Sun, 14 Oct 12 13:07:00 +0200</pubDate>
    <description>
 What a nice message in my mailbox this morning.

<p/>
<i>Hi Karel, 

<p/>Thought you might be interested in this, we are using XR to serve HTTP and HTTPS to our web farm (two XR instances) and this is the FD use count we are seeing ... sustained peak load of around 800 open sockets for several hours per day, and this would then be multiplied by two - one for each XR instance.

  <p/>
  <img src="/bld/Crossroads-Weekly.png"/>
  <p/>

  We had to up fs.file-max and net.ipv4.ip_local_port_range in sysctl - and increase ulimit. Other than that system configuration, it's performing brilliantly right out of the box.

<p/>Don't know if this is a 'large' load, but it's large to us.
</i>

<p/>
Thanks for letting me know, Malcolm V.!
 
</description>
   </item>
   <item>
    <title>The saddle seat</title>
    <link>http://www.kubat.nl/pages/blogaria/279#279</link>
    <pubDate>Wed, 10 Oct 12 11:34:27 +0200</pubDate>
    <description>
 Here's my new office chair. Very comfy and very ergonomic; I don't get a back pain when sitting for a few hours. The biggest bonus of course is that I get to play Cowboy in the office.

<p/>
<center>
  <img src="/bld/saddleseat/img_1462.jpg"/> &nbsp;&nbsp;
  <img src="/bld/saddleseat/img_1464.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Sudo Exploit</title>
    <link>http://www.kubat.nl/pages/blogaria/278#278</link>
    <pubDate>Sun, 30 Sep 12 01:56:53 +0200</pubDate>
    <description>
 Oldie but goldie. BTW this is for a really old sudo version. Don't
expect it to do you any good.

<p/>
<img src="/bld/SudoExploit.png"/>
 
</description>
   </item>
   <item>
    <title>Technomona is live</title>
    <link>http://www.kubat.nl/pages/blogaria/277#277</link>
    <pubDate>Sun, 30 Sep 12 01:55:23 +0200</pubDate>
    <description>
 <img src="/bld/Mona-Avatar.jpg" class="floatright"/>
<b>[Dutch]</b> De site <a href="http://www.technomona.nl/"
			  target="_blank">www.technomona.nl</a> is
live. Voor al uw vragen; Mona beantwoordt ze graag.
 
</description>
   </item>
   <item>
    <title>A Perl to HTML Prettyprinter</title>
    <link>http://www.kubat.nl/pages/blogaria/276#276</link>
    <pubDate>Thu, 20 Sep 12 09:36:27 +0200</pubDate>
    <description>
 I recently needed a little tool to convert a Perl source to
pretty-printed HTML; meaning colorized and entity-escaped. There are
some tools out there, but *almost* what I need.. so, here's what
I cooked up.

<p/>It's called src2html. It can provide line numbering on the output,
surround the generated listing with &lt;pre&gt; and &lt;/pre&gt;, or
surround the generated listing with a full HTML scaffold (for easy
viewing). It expands tabs so that the visual layout of e.g. indented
comments is preserved. It will quite nicely recognize Perl syntax and
follow it, though I didn't implement "here-documents" and
POD-surrounded blocks.

<p/> Here's the script src2html, for download. Instructions:
<ul>
  <li> <a href="/src2html" target="_blank">Click here</a> to download; </li>
  <li> Save the file somewhere on your system, e.g.
    in <i>/usr/local/bin</i>; </li>
  <li> Make the file executable using <i>chmod +x
      /usr/local/bin/src2html</i>; </li>
  <li> Use it as e.g.: <i>src2html myfile.pl &gt;
      output.html</i>; </li>
  <li> If you want to see "usage" information, just
    enter <i>src2html</i> for an overview of options; </li>
  <li> If you want to customize the layout of Perl parts - e.g., if
    you want to make strings stand out by typesetting them as boldface
    - then edit the script and change the pre- and post instructions
    in <i>%tokens</i> at the top of the file.</li>
</ul>

<p/>Here's the listing, of course formatted by itself.

<pre><font color="#909090"><i>    1</i></font>  <font color="#707070">#!/usr/bin/env perl</font>
<font color="#909090"><i>    2</i></font>  <font color="#0000aa">use</font> <font color="#0000fa">strict</font>;
<font color="#909090"><i>    3</i></font>  <font color="#0000aa">use</font> <font color="#0000fa">warnings</font>;
<font color="#909090"><i>    4</i></font>  <font color="#0000aa">use</font> <font color="#0000fa">Getopt</font>::<font color="#0000fa">Std</font>;
<font color="#909090"><i>    5</i></font>  
<font color="#909090"><i>    6</i></font>  <font color="#707070"># Lexical analyzer returns and their colorings.</font>
<font color="#909090"><i>    7</i></font>  <font color="#707070"># IDENTs are identifiers, such as a12_xyzzy;</font>
<font color="#909090"><i>    8</i></font>  <font color="#707070"># KEYWORDs are Perl keywords such as sub and return,</font>
<font color="#909090"><i>    9</i></font>  <font color="#707070"># OTHERs is a catch-all for operators etc,</font>
<font color="#909090"><i>   10</i></font>  <font color="#707070"># LINENO is a pseudo-token for coloring line numbers (flag -l)</font>
<font color="#909090"><i>   11</i></font>  <font color="#707070"># The pre and post values will surround the tokens.</font>
<font color="#909090"><i>   12</i></font>  <font color="#0000aa">my</font> %tokens = ( <font color="#ff1010"><i>'NEWLINE'</i></font> =&gt; <font color="#0000aa">undef</font>,
<font color="#909090"><i>   13</i></font>                 <font color="#ff1010"><i>'STRING'</i></font>  =&gt; { <font color="#0000fa">pre</font>  =&gt;   <font color="#ff1010"><i>'&lt;font color="#ff1010"&gt;&lt;i&gt;'</i></font>,
<font color="#909090"><i>   14</i></font>                                <font color="#0000fa">post</font> =&gt; <font color="#ff1010"><i>'&lt;/i&gt;&lt;/font&gt;'</i></font> }, 
<font color="#909090"><i>   15</i></font>                 <font color="#ff1010"><i>'COMMENT'</i></font> =&gt; { <font color="#0000fa">pre</font>  =&gt; <font color="#ff1010"><i>'&lt;font color="#707070"&gt;'</i></font>,
<font color="#909090"><i>   16</i></font>                                <font color="#0000fa">post</font> =&gt; <font color="#ff1010"><i>'&lt;/font&gt;'</i></font> },
<font color="#909090"><i>   17</i></font>                 <font color="#ff1010"><i>'SPACE'</i></font>   =&gt; <font color="#0000aa">undef</font>,
<font color="#909090"><i>   18</i></font>                 <font color="#ff1010"><i>'IDENT'</i></font>   =&gt; { <font color="#0000fa">pre</font>  =&gt; <font color="#ff1010"><i>'&lt;font color="#0000fa"&gt;'</i></font>,
<font color="#909090"><i>   19</i></font>                                <font color="#0000fa">post</font> =&gt; <font color="#ff1010"><i>'&lt;/font&gt;'</i></font> },
<font color="#909090"><i>   20</i></font>                 <font color="#ff1010"><i>'KEYWORD'</i></font> =&gt; { <font color="#0000fa">pre</font>  =&gt; <font color="#ff1010"><i>'&lt;font color="#0000aa"&gt;'</i></font>,
<font color="#909090"><i>   21</i></font>                                <font color="#0000fa">post</font> =&gt; <font color="#ff1010"><i>'&lt;/font&gt;'</i></font> },
<font color="#909090"><i>   22</i></font>                 <font color="#ff1010"><i>'OTHER'</i></font>   =&gt; <font color="#0000aa">undef</font>,
<font color="#909090"><i>   23</i></font>                 <font color="#ff1010"><i>'LINENO'</i></font>  =&gt; { <font color="#0000fa">pre</font>  =&gt; <font color="#ff1010"><i>'&lt;font color="#909090"&gt;&lt;i&gt;'</i></font>,
<font color="#909090"><i>   24</i></font>                                <font color="#0000fa">post</font> =&gt; <font color="#ff1010"><i>'&lt;/i&gt;&lt;/font&gt;'</i></font> }
<font color="#909090"><i>   25</i></font>               );
<font color="#909090"><i>   26</i></font>  
<font color="#909090"><i>   27</i></font>  <font color="#707070"># Parse cmd line flags and provide info.</font>
<font color="#909090"><i>   28</i></font>  <font color="#0000aa">my</font> %opts;
<font color="#909090"><i>   29</i></font>  (<font color="#0000fa">getopts</font>(<font color="#ff1010"><i>'phvl'</i></font>, \%opts) <font color="#0000aa">and</font> $<font color="#707070">#ARGV &gt;= 0)</font>
<font color="#909090"><i>   30</i></font>    <font color="#0000aa">or</font> <font color="#0000aa">die</font> &lt;&lt;<font color="#ff1010"><i>"ENDUSAGE"</i></font>;
<font color="#909090"><i>   31</i></font>  
<font color="#909090"><i>   32</i></font>  <font color="#0000fa">Usage</font>: <font color="#0000fa">src2html</font> [-<font color="#0000fa">phvl</font>] <font color="#0000fa">file</font>(<font color="#0000aa">s</font>)
<font color="#909090"><i>   33</i></font>  <font color="#0000fa">Flags</font>:
<font color="#909090"><i>   34</i></font>    -<font color="#0000fa">p</font>    <font color="#0000fa">surrounds</font> <font color="#0000fa">output</font> <font color="#0000fa">with</font> &lt;<font color="#0000fa">pre</font>&gt; <font color="#0000aa">and</font> &lt;/<font color="#0000fa">pre</font>&gt;
<font color="#909090"><i>   35</i></font>    -<font color="#0000fa">h</font>    <font color="#0000fa">writes</font> <font color="#0000fa">HTML</font> <font color="#0000fa">scaffolding</font> <font color="#0000fa">too</font> (<font color="#0000fa">implies</font> -<font color="#0000fa">p</font>)
<font color="#909090"><i>   36</i></font>    -<font color="#0000fa">v</font>    <font color="#0000fa">verbose</font> <font color="#0000fa">mode</font>, <font color="#0000fa">shows</font> <font color="#0000fa">lexical</font> <font color="#0000fa">keywords</font> <font color="#0000fa">on</font> <font color="#0000fa">stderr</font> (<font color="#0000aa">for</font> <font color="#0000fa">debugging</font>)
<font color="#909090"><i>   37</i></font>    -<font color="#0000fa">l</font>    <font color="#0000fa">prefixes</font> <font color="#0000fa">output</font> <font color="#0000fa">with</font> <font color="#0000fa">line</font> <font color="#0000fa">numbers</font>
<font color="#909090"><i>   38</i></font>  <font color="#0000fa">File</font>(<font color="#0000aa">s</font>):
<font color="#909090"><i>   39</i></font>    <font color="#0000fa">Files</font> <font color="#0000fa">to</font> <font color="#0000fa">process</font>, <font color="#0000aa">use</font> - <font color="#0000fa">to</font> <font color="#0000aa">read</font> <font color="#0000fa">from</font> <font color="#0000fa">stdin</font>
<font color="#909090"><i>   40</i></font>  
<font color="#909090"><i>   41</i></font>  <font color="#0000fa">The</font> <font color="#0000fa">input</font> <font color="#0000fa">in</font> <font color="#0000fa">file</font>(<font color="#0000aa">s</font>) <font color="#0000fa">is</font> <font color="#0000fa">taken</font> <font color="#0000fa">as</font> <font color="#0000fa">source</font> <font color="#0000aa">and</font> <font color="#0000fa">colorprinted</font> <font color="#0000fa">to</font> <font color="#0000fa">stdout</font> <font color="#0000fa">in</font> <font color="#0000fa">HTML</font>
<font color="#909090"><i>   42</i></font>  <font color="#0000fa">syntax</font>.
<font color="#909090"><i>   43</i></font>  
<font color="#909090"><i>   44</i></font>  <font color="#0000fa">ENDUSAGE</font>
<font color="#909090"><i>   45</i></font>  
<font color="#909090"><i>   46</i></font>  <font color="#707070"># Perl keywords, taken from http://learn.perl.org/docs/keywords.html</font>
<font color="#909090"><i>   47</i></font>  <font color="#0000aa">use</font> <font color="#0000fa">constant</font> <font color="#0000fa">KEYWORDS</font> =&gt;
<font color="#909090"><i>   48</i></font>    <font color="#0000aa">qw</font>(-<font color="#0000fa">A</font> <font color="#0000aa">END</font> <font color="#0000aa">length</font> <font color="#0000aa">setpgrp</font> 
<font color="#909090"><i>   49</i></font>       -<font color="#0000fa">B</font> <font color="#0000aa">endgrent</font> <font color="#0000aa">link</font> <font color="#0000aa">setpriority</font> 
<font color="#909090"><i>   50</i></font>       -<font color="#0000fa">b</font> <font color="#0000aa">endhostent</font> <font color="#0000aa">listen</font> <font color="#0000aa">setprotoent</font> 
<font color="#909090"><i>   51</i></font>       -<font color="#0000fa">C</font> <font color="#0000aa">endnetent</font> <font color="#0000aa">local</font> <font color="#0000aa">setpwent</font> 
<font color="#909090"><i>   52</i></font>       -<font color="#0000fa">c</font> <font color="#0000aa">endprotoent</font> <font color="#0000aa">localtime</font> <font color="#0000aa">setservent</font> 
<font color="#909090"><i>   53</i></font>       -<font color="#0000fa">d</font> <font color="#0000aa">endpwent</font> <font color="#0000aa">log</font> <font color="#0000aa">setsockopt</font> 
<font color="#909090"><i>   54</i></font>       -<font color="#0000fa">e</font> <font color="#0000aa">endservent</font> <font color="#0000aa">lstat</font> <font color="#0000aa">shift</font> 
<font color="#909090"><i>   55</i></font>       -<font color="#0000fa">f</font> <font color="#0000aa">eof</font> <font color="#0000aa">map</font> <font color="#0000aa">shmctl</font> 
<font color="#909090"><i>   56</i></font>       -<font color="#0000fa">g</font> <font color="#0000aa">eval</font> <font color="#0000aa">mkdir</font> <font color="#0000aa">shmget</font> 
<font color="#909090"><i>   57</i></font>       -<font color="#0000fa">k</font> <font color="#0000aa">exec</font> <font color="#0000aa">msgctl</font> <font color="#0000aa">shmread</font> 
<font color="#909090"><i>   58</i></font>       -<font color="#0000fa">l</font> <font color="#0000aa">exists</font> <font color="#0000aa">msgget</font> <font color="#0000aa">shmwrite</font> 
<font color="#909090"><i>   59</i></font>       -<font color="#0000fa">M</font> <font color="#0000aa">exit</font> <font color="#0000aa">msgrcv</font> <font color="#0000aa">shutdown</font> 
<font color="#909090"><i>   60</i></font>       -<font color="#0000fa">O</font> <font color="#0000aa">fcntl</font> <font color="#0000aa">msgsnd</font> <font color="#0000aa">sin</font> 
<font color="#909090"><i>   61</i></font>       -<font color="#0000fa">o</font> <font color="#0000aa">fileno</font> <font color="#0000aa">my</font> <font color="#0000aa">sleep</font> 
<font color="#909090"><i>   62</i></font>       -<font color="#0000fa">p</font> <font color="#0000aa">flock</font> <font color="#0000aa">next</font> <font color="#0000aa">socket</font> 
<font color="#909090"><i>   63</i></font>       -<font color="#0000fa">r</font> <font color="#0000aa">fork</font> <font color="#0000aa">not</font> <font color="#0000aa">socketpair</font> 
<font color="#909090"><i>   64</i></font>       -<font color="#0000fa">R</font> <font color="#0000aa">format</font> <font color="#0000aa">oct</font> <font color="#0000aa">sort</font> 
<font color="#909090"><i>   65</i></font>       -<font color="#0000fa">S</font> <font color="#0000aa">formline</font> <font color="#0000aa">open</font> <font color="#0000aa">splice</font> 
<font color="#909090"><i>   66</i></font>       -<font color="#0000aa">s</font> <font color="#0000aa">getc</font> <font color="#0000aa">opendir</font> <font color="#0000aa">split</font> 
<font color="#909090"><i>   67</i></font>       -<font color="#0000fa">T</font> <font color="#0000aa">getgrent</font> <font color="#0000aa">ord</font> <font color="#0000aa">sprintf</font> 
<font color="#909090"><i>   68</i></font>       -<font color="#0000fa">t</font> <font color="#0000aa">getgrgid</font> <font color="#0000aa">our</font> <font color="#0000aa">sqrt</font> 
<font color="#909090"><i>   69</i></font>       -<font color="#0000fa">u</font> <font color="#0000aa">getgrnam</font> <font color="#0000aa">pack</font> <font color="#0000aa">srand</font> 
<font color="#909090"><i>   70</i></font>       -<font color="#0000fa">w</font> <font color="#0000aa">gethostbyaddr</font> <font color="#0000aa">pipe</font> <font color="#0000aa">stat</font> 
<font color="#909090"><i>   71</i></font>       -<font color="#0000fa">W</font> <font color="#0000aa">gethostbyname</font> <font color="#0000aa">pop</font> <font color="#0000aa">state</font> 
<font color="#909090"><i>   72</i></font>       -<font color="#0000fa">X</font> <font color="#0000aa">gethostent</font> <font color="#0000aa">pos</font> <font color="#0000aa">study</font> 
<font color="#909090"><i>   73</i></font>       -<font color="#0000fa">x</font> <font color="#0000aa">getlogin</font> <font color="#0000aa">print</font> <font color="#0000aa">substr</font> 
<font color="#909090"><i>   74</i></font>       -<font color="#0000fa">z</font> <font color="#0000aa">getnetbyaddr</font> <font color="#0000aa">printf</font> <font color="#0000aa">symlink</font> 
<font color="#909090"><i>   75</i></font>       <font color="#0000aa">abs</font> <font color="#0000aa">getnetbyname</font> <font color="#0000aa">prototype</font> <font color="#0000aa">syscall</font> 
<font color="#909090"><i>   76</i></font>       <font color="#0000aa">accept</font> <font color="#0000aa">getnetent</font> <font color="#0000aa">push</font> <font color="#0000aa">sysopen</font> 
<font color="#909090"><i>   77</i></font>       <font color="#0000aa">alarm</font> <font color="#0000aa">getpeername</font> <font color="#0000aa">quotemeta</font> <font color="#0000aa">sysread</font> 
<font color="#909090"><i>   78</i></font>       <font color="#0000aa">atan2</font> <font color="#0000aa">getpgrp</font> <font color="#0000aa">rand</font> <font color="#0000aa">sysseek</font> 
<font color="#909090"><i>   79</i></font>       <font color="#0000aa">AUTOLOAD</font> <font color="#0000aa">getppid</font> <font color="#0000aa">read</font> <font color="#0000aa">system</font> 
<font color="#909090"><i>   80</i></font>       <font color="#0000aa">BEGIN</font> <font color="#0000aa">getpriority</font> <font color="#0000aa">readdir</font> <font color="#0000aa">syswrite</font> 
<font color="#909090"><i>   81</i></font>       <font color="#0000aa">bind</font> <font color="#0000aa">getprotobyname</font> <font color="#0000aa">readline</font> <font color="#0000aa">tell</font> 
<font color="#909090"><i>   82</i></font>       <font color="#0000aa">binmode</font> <font color="#0000aa">getprotobynumber</font> <font color="#0000aa">readlink</font> <font color="#0000aa">telldir</font> 
<font color="#909090"><i>   83</i></font>       <font color="#0000aa">bless</font> <font color="#0000aa">getprotoent</font> <font color="#0000aa">readpipe</font> <font color="#0000aa">tie</font> 
<font color="#909090"><i>   84</i></font>       <font color="#0000aa">break</font> <font color="#0000aa">getpwent</font> <font color="#0000aa">recv</font> <font color="#0000aa">tied</font> 
<font color="#909090"><i>   85</i></font>       <font color="#0000aa">caller</font> <font color="#0000aa">getpwnam</font> <font color="#0000aa">redo</font> <font color="#0000aa">time</font> 
<font color="#909090"><i>   86</i></font>       <font color="#0000aa">chdir</font> <font color="#0000aa">getpwuid</font> <font color="#0000aa">ref</font> <font color="#0000aa">times</font> 
<font color="#909090"><i>   87</i></font>       <font color="#0000aa">CHECK</font> <font color="#0000aa">getservbyname</font> <font color="#0000aa">rename</font> <font color="#0000aa">truncate</font> 
<font color="#909090"><i>   88</i></font>       <font color="#0000aa">chmod</font> <font color="#0000aa">getservbyport</font> <font color="#0000aa">require</font> <font color="#0000aa">uc</font> 
<font color="#909090"><i>   89</i></font>       <font color="#0000aa">chomp</font> <font color="#0000aa">getservent</font> <font color="#0000aa">reset</font> <font color="#0000aa">ucfirst</font> 
<font color="#909090"><i>   90</i></font>       <font color="#0000aa">chop</font> <font color="#0000aa">getsockname</font> <font color="#0000aa">return</font> <font color="#0000aa">umask</font> 
<font color="#909090"><i>   91</i></font>       <font color="#0000aa">chown</font> <font color="#0000aa">getsockopt</font> <font color="#0000aa">reverse</font> <font color="#0000aa">undef</font> 
<font color="#909090"><i>   92</i></font>       <font color="#0000aa">chr</font> <font color="#0000aa">glob</font> <font color="#0000aa">rewinddir</font> <font color="#0000aa">UNITCHECK</font> 
<font color="#909090"><i>   93</i></font>       <font color="#0000aa">chroot</font> <font color="#0000aa">gmtime</font> <font color="#0000aa">rindex</font> <font color="#0000aa">unlink</font> 
<font color="#909090"><i>   94</i></font>       <font color="#0000aa">close</font> <font color="#0000aa">goto</font> <font color="#0000aa">rmdir</font> <font color="#0000aa">unpack</font> 
<font color="#909090"><i>   95</i></font>       <font color="#0000aa">closedir</font> <font color="#0000aa">grep</font> <font color="#0000aa">say</font> <font color="#0000aa">unshift</font> 
<font color="#909090"><i>   96</i></font>       <font color="#0000aa">connect</font> <font color="#0000aa">hex</font> <font color="#0000aa">scalar</font> <font color="#0000aa">untie</font> 
<font color="#909090"><i>   97</i></font>       <font color="#0000aa">cos</font> <font color="#0000aa">index</font> <font color="#0000aa">seek</font> <font color="#0000aa">use</font> 
<font color="#909090"><i>   98</i></font>       <font color="#0000aa">crypt</font> <font color="#0000aa">INIT</font> <font color="#0000aa">seekdir</font> <font color="#0000aa">utime</font> 
<font color="#909090"><i>   99</i></font>       <font color="#0000aa">dbmclose</font> <font color="#0000aa">int</font> <font color="#0000aa">select</font> <font color="#0000aa">values</font> 
<font color="#909090"><i>  100</i></font>       <font color="#0000aa">dbmopen</font> <font color="#0000aa">ioctl</font> <font color="#0000aa">semctl</font> <font color="#0000aa">vec</font> 
<font color="#909090"><i>  101</i></font>       <font color="#0000aa">defined</font> <font color="#0000aa">join</font> <font color="#0000aa">semget</font> <font color="#0000aa">wait</font> 
<font color="#909090"><i>  102</i></font>       <font color="#0000aa">delete</font> <font color="#0000aa">keys</font> <font color="#0000aa">semop</font> <font color="#0000aa">waitpid</font> 
<font color="#909090"><i>  103</i></font>       <font color="#0000aa">DESTROY</font> <font color="#0000aa">kill</font> <font color="#0000aa">send</font> <font color="#0000aa">wantarray</font> 
<font color="#909090"><i>  104</i></font>       <font color="#0000aa">die</font> <font color="#0000aa">last</font> <font color="#0000aa">setgrent</font> <font color="#0000aa">warn</font> 
<font color="#909090"><i>  105</i></font>       <font color="#0000aa">dump</font> <font color="#0000aa">lc</font> <font color="#0000aa">sethostent</font> <font color="#0000aa">write</font> 
<font color="#909090"><i>  106</i></font>       <font color="#0000aa">each</font> <font color="#0000aa">lcfirst</font> <font color="#0000aa">setnetent</font>  
<font color="#909090"><i>  107</i></font>  
<font color="#909090"><i>  108</i></font>       <font color="#0000aa">__DATA__</font> <font color="#0000aa">else</font> <font color="#0000aa">lock</font> <font color="#0000aa">qw</font> 
<font color="#909090"><i>  109</i></font>       <font color="#0000aa">__END__</font> <font color="#0000aa">elsif</font> <font color="#0000aa">lt</font> <font color="#0000aa">qx</font> 
<font color="#909090"><i>  110</i></font>       <font color="#0000aa">__FILE__</font> <font color="#0000aa">eq</font> <font color="#0000aa">m</font> <font color="#0000aa">s</font> 
<font color="#909090"><i>  111</i></font>       <font color="#0000aa">__LINE__</font> <font color="#0000aa">exp</font> <font color="#0000aa">ne</font> <font color="#0000aa">sub</font> 
<font color="#909090"><i>  112</i></font>       <font color="#0000aa">__PACKAGE__</font> <font color="#0000aa">for</font> <font color="#0000aa">no</font> <font color="#0000aa">tr</font> 
<font color="#909090"><i>  113</i></font>       <font color="#0000aa">and</font> <font color="#0000aa">foreach</font> <font color="#0000aa">or</font> <font color="#0000aa">unless</font> 
<font color="#909090"><i>  114</i></font>       <font color="#0000aa">cmp</font> <font color="#0000aa">ge</font> <font color="#0000aa">package</font> <font color="#0000aa">until</font> 
<font color="#909090"><i>  115</i></font>       <font color="#0000aa">continue</font> <font color="#0000aa">gt</font> <font color="#0000aa">q</font> <font color="#0000aa">while</font> 
<font color="#909090"><i>  116</i></font>       <font color="#0000aa">CORE</font> <font color="#0000aa">if</font> <font color="#0000aa">qq</font> <font color="#0000aa">xor</font> 
<font color="#909090"><i>  117</i></font>       <font color="#0000aa">do</font> <font color="#0000aa">le</font> <font color="#0000aa">qr</font> <font color="#0000aa">y</font>
<font color="#909090"><i>  118</i></font>       
<font color="#909090"><i>  119</i></font>       <font color="#0000aa">ARGV</font> <font color="#0000aa">STDERR</font> <font color="#0000aa">STDOUT</font> 
<font color="#909090"><i>  120</i></font>       <font color="#0000aa">ARGVOUT</font> <font color="#0000aa">STDIN</font>  
<font color="#909090"><i>  121</i></font>     );
<font color="#909090"><i>  122</i></font>  
<font color="#909090"><i>  123</i></font>  <font color="#707070"># Reverse map of the keywords</font>
<font color="#909090"><i>  124</i></font>  <font color="#0000aa">my</font> %keywordmap;
<font color="#909090"><i>  125</i></font>  <font color="#0000aa">for</font> <font color="#0000aa">my</font> $key (<font color="#0000fa">KEYWORDS</font>) {
<font color="#909090"><i>  126</i></font>      $keywordmap{$key} = 1;
<font color="#909090"><i>  127</i></font>  }
<font color="#909090"><i>  128</i></font>  
<font color="#909090"><i>  129</i></font>  <font color="#707070"># Parse all files and send to stdout.</font>
<font color="#909090"><i>  130</i></font>  $opts{<font color="#0000fa">p</font>}++ <font color="#0000aa">if</font> ($opts{<font color="#0000fa">h</font>});
<font color="#909090"><i>  131</i></font>  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&lt;html&gt;&lt;body&gt;\n"</i></font>) <font color="#0000aa">if</font> ($opts{<font color="#0000fa">h</font>});
<font color="#909090"><i>  132</i></font>  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&lt;pre&gt;"</i></font>) <font color="#0000aa">if</font> ($opts{<font color="#0000fa">p</font>});
<font color="#909090"><i>  133</i></font>  <font color="#0000aa">for</font> <font color="#0000aa">my</font> $f (@ARGV) {
<font color="#909090"><i>  134</i></font>      <font color="#0000aa">open</font>(<font color="#0000aa">my</font> $if, $f) <font color="#0000aa">or</font> <font color="#0000aa">die</font>(<font color="#ff1010"><i>"Cannot read $f: $!\n"</i></font>);
<font color="#909090"><i>  135</i></font>      <font color="#0000fa">process</font>($if);                      
<font color="#909090"><i>  136</i></font>  }
<font color="#909090"><i>  137</i></font>  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&lt;/pre&gt;"</i></font>) <font color="#0000aa">if</font> ($opts{<font color="#0000fa">p</font>});
<font color="#909090"><i>  138</i></font>  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&lt;/body&gt;&lt;/html&gt;"</i></font>) <font color="#0000aa">if</font> ($opts{<font color="#0000fa">h</font>});
<font color="#909090"><i>  139</i></font>  
<font color="#909090"><i>  140</i></font>  <font color="#707070"># Process a file</font>
<font color="#909090"><i>  141</i></font>  <font color="#0000aa">sub</font> <font color="#0000fa">process</font> {
<font color="#909090"><i>  142</i></font>      <font color="#0000aa">my</font> $if = <font color="#0000aa">shift</font>;
<font color="#909090"><i>  143</i></font>      <font color="#0000aa">my</font> $at_linestart = 1;
<font color="#909090"><i>  144</i></font>      <font color="#0000aa">my</font> $lineno = 1;
<font color="#909090"><i>  145</i></font>  
<font color="#909090"><i>  146</i></font>      <font color="#0000aa">while</font> (1) {
<font color="#909090"><i>  147</i></font>          <font color="#0000aa">my</font> ($token, $semantic) = <font color="#0000fa">lex</font>($if);
<font color="#909090"><i>  148</i></font>          <font color="#0000aa">last</font> <font color="#0000aa">unless</font> (<font color="#0000aa">defined</font> $token <font color="#0000aa">and</font> <font color="#0000aa">defined</font> $semantic);
<font color="#909090"><i>  149</i></font>          <font color="#0000aa">my</font> $pre = <font color="#ff1010"><i>''</i></font>;
<font color="#909090"><i>  150</i></font>          <font color="#0000aa">my</font> $post = <font color="#ff1010"><i>''</i></font>;
<font color="#909090"><i>  151</i></font>          <font color="#0000aa">if</font> (<font color="#0000aa">defined</font> ($tokens{$token})) {
<font color="#909090"><i>  152</i></font>              $pre  = $tokens{$token}-&gt;{<font color="#0000fa">pre</font>};
<font color="#909090"><i>  153</i></font>              $post = $tokens{$token}-&gt;{<font color="#0000fa">post</font>};
<font color="#909090"><i>  154</i></font>          }
<font color="#909090"><i>  155</i></font>  
<font color="#909090"><i>  156</i></font>          <font color="#0000aa">if</font> ($opts{<font color="#0000fa">v</font>}) {
<font color="#909090"><i>  157</i></font>              <font color="#0000aa">print</font> <font color="#0000aa">STDERR</font> (<font color="#ff1010"><i>"Token: $token"</i></font>);
<font color="#909090"><i>  158</i></font>              <font color="#0000aa">print</font> <font color="#0000aa">STDERR</font> (<font color="#ff1010"><i>", semantic: $semantic"</i></font>) <font color="#0000aa">if</font> ($token <font color="#0000aa">ne</font> <font color="#ff1010"><i>'NEWLINE'</i></font>);
<font color="#909090"><i>  159</i></font>              <font color="#0000aa">print</font> <font color="#0000aa">STDERR</font> (<font color="#ff1010"><i>", layout: $pre TEXT $post"</i></font>)
<font color="#909090"><i>  160</i></font>                <font color="#0000aa">if</font> ($pre <font color="#0000aa">ne</font> <font color="#ff1010"><i>''</i></font> <font color="#0000aa">or</font> $post <font color="#0000aa">ne</font> <font color="#ff1010"><i>''</i></font>);
<font color="#909090"><i>  161</i></font>              <font color="#0000aa">print</font> <font color="#0000aa">STDERR</font> (<font color="#ff1010"><i>"\n"</i></font>);
<font color="#909090"><i>  162</i></font>          }
<font color="#909090"><i>  163</i></font>  
<font color="#909090"><i>  164</i></font>          <font color="#0000aa">if</font> ($opts{<font color="#0000fa">l</font>} <font color="#0000aa">and</font> $at_linestart) {
<font color="#909090"><i>  165</i></font>              <font color="#0000aa">my</font> $lpre  = <font color="#ff1010"><i>''</i></font>;
<font color="#909090"><i>  166</i></font>              <font color="#0000aa">my</font> $lpost = <font color="#ff1010"><i>''</i></font>;
<font color="#909090"><i>  167</i></font>              <font color="#0000aa">if</font> (<font color="#0000aa">defined</font>($tokens{<font color="#0000fa">LINENO</font>})) {
<font color="#909090"><i>  168</i></font>                  $lpre  = $tokens{<font color="#0000fa">LINENO</font>}-&gt;{<font color="#0000fa">pre</font>};
<font color="#909090"><i>  169</i></font>                  $lpost = $tokens{<font color="#0000fa">LINENO</font>}-&gt;{<font color="#0000fa">post</font>};
<font color="#909090"><i>  170</i></font>              }
<font color="#909090"><i>  171</i></font>              <font color="#0000aa">printf</font>(<font color="#ff1010"><i>'%s%5d%s  '</i></font>, $lpre, $lineno++, $lpost);
<font color="#909090"><i>  172</i></font>              $at_linestart = <font color="#0000aa">undef</font>;
<font color="#909090"><i>  173</i></font>          }
<font color="#909090"><i>  174</i></font>  
<font color="#909090"><i>  175</i></font>          <font color="#0000aa">print</font>($pre);
<font color="#909090"><i>  176</i></font>          <font color="#0000aa">for</font> <font color="#0000aa">my</font> $ch (<font color="#0000aa">split</font>(<font color="#ff1010"><i>''</i></font>, $semantic)) {
<font color="#909090"><i>  177</i></font>              <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>'&lt;'</i></font>) {
<font color="#909090"><i>  178</i></font>                  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&amp;lt;"</i></font>);
<font color="#909090"><i>  179</i></font>              } <font color="#0000aa">elsif</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>'&gt;'</i></font>) {
<font color="#909090"><i>  180</i></font>                  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&amp;gt;"</i></font>);
<font color="#909090"><i>  181</i></font>              } <font color="#0000aa">elsif</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>'&amp;'</i></font>) {
<font color="#909090"><i>  182</i></font>                  <font color="#0000aa">print</font>(<font color="#ff1010"><i>"&amp;amp;"</i></font>);
<font color="#909090"><i>  183</i></font>              } <font color="#0000aa">else</font> {
<font color="#909090"><i>  184</i></font>                  <font color="#0000aa">print</font>($ch);
<font color="#909090"><i>  185</i></font>              }
<font color="#909090"><i>  186</i></font>          }
<font color="#909090"><i>  187</i></font>          <font color="#0000aa">print</font>($post);
<font color="#909090"><i>  188</i></font>          
<font color="#909090"><i>  189</i></font>          $at_linestart = 1 <font color="#0000aa">if</font> ($token <font color="#0000aa">eq</font> <font color="#ff1010"><i>'NEWLINE'</i></font>);
<font color="#909090"><i>  190</i></font>      }
<font color="#909090"><i>  191</i></font>  }
<font color="#909090"><i>  192</i></font>  
<font color="#909090"><i>  193</i></font>  <font color="#0000aa">my</font> $col = 0;            <font color="#707070"># Column in input, updated by getchar() below</font>
<font color="#909090"><i>  194</i></font>  
<font color="#909090"><i>  195</i></font>  <font color="#707070"># Lexical analyzer</font>
<font color="#909090"><i>  196</i></font>  <font color="#0000aa">sub</font> <font color="#0000fa">lex</font> {
<font color="#909090"><i>  197</i></font>      <font color="#0000aa">my</font> $if  = <font color="#0000aa">shift</font>;
<font color="#909090"><i>  198</i></font>      <font color="#0000aa">my</font> $sem = <font color="#0000aa">undef</font>;
<font color="#909090"><i>  199</i></font>      <font color="#0000aa">my</font> $ch;
<font color="#909090"><i>  200</i></font>  
<font color="#909090"><i>  201</i></font>      <font color="#0000aa">while</font> (1) {
<font color="#909090"><i>  202</i></font>          $ch = <font color="#0000fa">getchar</font>($if);
<font color="#909090"><i>  203</i></font>  
<font color="#909090"><i>  204</i></font>          <font color="#707070"># EOF</font>
<font color="#909090"><i>  205</i></font>          <font color="#0000aa">return</font> (<font color="#0000aa">undef</font>, <font color="#0000aa">undef</font>) <font color="#0000aa">unless</font> (<font color="#0000aa">defined</font>($ch));
<font color="#909090"><i>  206</i></font>          
<font color="#909090"><i>  207</i></font>          <font color="#707070"># NEWLINE return</font>
<font color="#909090"><i>  208</i></font>          <font color="#0000aa">return</font> (<font color="#ff1010"><i>'NEWLINE'</i></font>, <font color="#ff1010"><i>"\n"</i></font>) <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>"\n"</i></font>);
<font color="#909090"><i>  209</i></font>  
<font color="#909090"><i>  210</i></font>          <font color="#707070"># Start the semantic buffer.</font>
<font color="#909090"><i>  211</i></font>          $sem .= $ch;    
<font color="#909090"><i>  212</i></font>  
<font color="#909090"><i>  213</i></font>          <font color="#707070"># STRING return</font>
<font color="#909090"><i>  214</i></font>          <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>'"'</i></font> <font color="#0000aa">or</font> $ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>"\'"</i></font>) {
<font color="#909090"><i>  215</i></font>              <font color="#0000aa">my</font> $startchar = $ch;
<font color="#909090"><i>  216</i></font>              <font color="#0000aa">do</font> {
<font color="#909090"><i>  217</i></font>                  $ch = <font color="#0000fa">getchar</font>($if);
<font color="#909090"><i>  218</i></font>                  $sem .= $ch;
<font color="#909090"><i>  219</i></font>                  <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>"\\"</i></font>) {
<font color="#909090"><i>  220</i></font>                      $ch = <font color="#0000fa">getchar</font>($if);
<font color="#909090"><i>  221</i></font>                      $sem .= $ch;
<font color="#909090"><i>  222</i></font>                  }
<font color="#909090"><i>  223</i></font>              } <font color="#0000aa">while</font> ($ch <font color="#0000aa">ne</font> $startchar);
<font color="#909090"><i>  224</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'STRING'</i></font>, $sem);
<font color="#909090"><i>  225</i></font>          }
<font color="#909090"><i>  226</i></font>  
<font color="#909090"><i>  227</i></font>          <font color="#707070"># COMMENT return</font>
<font color="#909090"><i>  228</i></font>          <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>'#'</i></font>) {
<font color="#909090"><i>  229</i></font>              <font color="#0000aa">while</font> (1) {
<font color="#909090"><i>  230</i></font>                  <font color="#0000aa">my</font> $peek = <font color="#0000fa">peekchar</font>($if);
<font color="#909090"><i>  231</i></font>                  <font color="#0000aa">if</font> ($peek <font color="#0000aa">ne</font> <font color="#ff1010"><i>"\n"</i></font>) {
<font color="#909090"><i>  232</i></font>                      $sem .= <font color="#0000fa">getchar</font>($if);
<font color="#909090"><i>  233</i></font>                  } <font color="#0000aa">else</font> {
<font color="#909090"><i>  234</i></font>                      <font color="#0000aa">last</font>;
<font color="#909090"><i>  235</i></font>                  }
<font color="#909090"><i>  236</i></font>              }
<font color="#909090"><i>  237</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'COMMENT'</i></font>, $sem);
<font color="#909090"><i>  238</i></font>          }
<font color="#909090"><i>  239</i></font>  
<font color="#909090"><i>  240</i></font>          <font color="#707070"># SPACE return - plain whitespace</font>
<font color="#909090"><i>  241</i></font>          <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>' '</i></font>) {
<font color="#909090"><i>  242</i></font>              <font color="#0000aa">while</font> (1) {
<font color="#909090"><i>  243</i></font>                  <font color="#0000aa">my</font> $peek = <font color="#0000fa">peekchar</font>($if);
<font color="#909090"><i>  244</i></font>                  <font color="#0000aa">if</font> ($peek <font color="#0000aa">eq</font> <font color="#ff1010"><i>' '</i></font>) {
<font color="#909090"><i>  245</i></font>                      $sem .= <font color="#0000fa">getchar</font>($if);
<font color="#909090"><i>  246</i></font>                  } <font color="#0000aa">else</font> {
<font color="#909090"><i>  247</i></font>                      <font color="#0000aa">last</font>;
<font color="#909090"><i>  248</i></font>                  }
<font color="#909090"><i>  249</i></font>              }
<font color="#909090"><i>  250</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'SPACE'</i></font>, $sem);
<font color="#909090"><i>  251</i></font>          }
<font color="#909090"><i>  252</i></font>  
<font color="#909090"><i>  253</i></font>          <font color="#707070"># SPACE return - detabbed \t</font>
<font color="#909090"><i>  254</i></font>          <font color="#0000aa">if</font> ($ch <font color="#0000aa">eq</font> <font color="#ff1010"><i>"\t"</i></font>) {
<font color="#909090"><i>  255</i></font>              $sem = <font color="#ff1010"><i>''</i></font>;
<font color="#909090"><i>  256</i></font>              <font color="#707070"># ++$col unless ($col % 8);</font>
<font color="#909090"><i>  257</i></font>              <font color="#0000aa">while</font> ($col % 8) {
<font color="#909090"><i>  258</i></font>                  $sem .= <font color="#ff1010"><i>' '</i></font>;
<font color="#909090"><i>  259</i></font>                  ++$col;
<font color="#909090"><i>  260</i></font>              }
<font color="#909090"><i>  261</i></font>              $sem .= <font color="#ff1010"><i>' '</i></font>;
<font color="#909090"><i>  262</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'SPACE'</i></font>, $sem);
<font color="#909090"><i>  263</i></font>          }
<font color="#909090"><i>  264</i></font>  
<font color="#909090"><i>  265</i></font>          <font color="#707070"># IDENT return</font>
<font color="#909090"><i>  266</i></font>          <font color="#0000aa">if</font> ($ch =~ /[<font color="#0000fa">_a</font>-<font color="#0000fa">z</font>\%\$\&amp;\@]/<font color="#0000fa">i</font>) {
<font color="#909090"><i>  267</i></font>              <font color="#0000aa">while</font> (1) {
<font color="#909090"><i>  268</i></font>                  <font color="#0000aa">my</font> $peek = <font color="#0000fa">peekchar</font>($if);
<font color="#909090"><i>  269</i></font>                  <font color="#0000aa">if</font> ($peek =~ /[<font color="#0000fa">_a</font>-<font color="#0000fa">z0</font>-9\%\$\&amp;\@]/<font color="#0000fa">i</font>) {
<font color="#909090"><i>  270</i></font>                      $sem .= <font color="#0000fa">getchar</font>($if);
<font color="#909090"><i>  271</i></font>                  } <font color="#0000aa">else</font> {
<font color="#909090"><i>  272</i></font>                      <font color="#0000aa">last</font>;
<font color="#909090"><i>  273</i></font>                  }
<font color="#909090"><i>  274</i></font>              }
<font color="#909090"><i>  275</i></font>              <font color="#707070"># Identifiers that are keywords become a.. umm keyword</font>
<font color="#909090"><i>  276</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'KEYWORD'</i></font>, $sem) <font color="#0000aa">if</font> ($keywordmap{$sem});
<font color="#909090"><i>  277</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'IDENT'</i></font>, $sem)   <font color="#0000aa">if</font> ($sem =~ /^[<font color="#0000fa">a</font>-<font color="#0000fa">z0</font>-9<font color="#0000fa">_</font>]+$/<font color="#0000fa">i</font>);
<font color="#909090"><i>  278</i></font>              <font color="#0000aa">return</font> (<font color="#ff1010"><i>'OTHER'</i></font>, $sem);
<font color="#909090"><i>  279</i></font>          }
<font color="#909090"><i>  280</i></font>  
<font color="#909090"><i>  281</i></font>          <font color="#707070"># OTHER return catch-all</font>
<font color="#909090"><i>  282</i></font>          <font color="#0000aa">return</font> (<font color="#ff1010"><i>'OTHER'</i></font>, $sem);
<font color="#909090"><i>  283</i></font>      }
<font color="#909090"><i>  284</i></font>  }
<font color="#909090"><i>  285</i></font>  
<font color="#909090"><i>  286</i></font>  <font color="#707070"># Get a character from the input stream, with capability of 1 peek-ahead</font>
<font color="#909090"><i>  287</i></font>  <font color="#0000aa">my</font> $peekchar = <font color="#0000aa">undef</font>;
<font color="#909090"><i>  288</i></font>  <font color="#0000aa">sub</font> <font color="#0000fa">peekchar</font> {
<font color="#909090"><i>  289</i></font>      <font color="#0000aa">my</font> $if = <font color="#0000aa">shift</font>;
<font color="#909090"><i>  290</i></font>      
<font color="#909090"><i>  291</i></font>      $peekchar = <font color="#0000aa">undef</font> <font color="#0000aa">if</font> (<font color="#0000aa">read</font>($if, $peekchar, 1) &lt; 1);
<font color="#909090"><i>  292</i></font>      <font color="#0000aa">return</font> $peekchar;
<font color="#909090"><i>  293</i></font>  }
<font color="#909090"><i>  294</i></font>  <font color="#0000aa">sub</font> <font color="#0000fa">getchar</font> {
<font color="#909090"><i>  295</i></font>      <font color="#0000aa">my</font> $if = <font color="#0000aa">shift</font>;
<font color="#909090"><i>  296</i></font>      <font color="#0000aa">my</font> $ret;
<font color="#909090"><i>  297</i></font>      
<font color="#909090"><i>  298</i></font>      <font color="#0000aa">if</font> (<font color="#0000aa">defined</font>($peekchar)) {
<font color="#909090"><i>  299</i></font>          $ret = $peekchar;
<font color="#909090"><i>  300</i></font>          $peekchar = <font color="#0000aa">undef</font>;
<font color="#909090"><i>  301</i></font>      } <font color="#0000aa">else</font> {
<font color="#909090"><i>  302</i></font>          $ret = <font color="#0000aa">undef</font> <font color="#0000aa">if</font> (<font color="#0000aa">read</font>($if, $ret, 1) &lt; 1);       
<font color="#909090"><i>  303</i></font>      }
<font color="#909090"><i>  304</i></font>      <font color="#0000aa">if</font> (<font color="#0000aa">defined</font>($ret) <font color="#0000aa">and</font> $ret <font color="#0000aa">eq</font> <font color="#ff1010"><i>"\n"</i></font>) {
<font color="#909090"><i>  305</i></font>          $col = 0;
<font color="#909090"><i>  306</i></font>      } <font color="#0000aa">else</font> {
<font color="#909090"><i>  307</i></font>          ++$col;
<font color="#909090"><i>  308</i></font>      }
<font color="#909090"><i>  309</i></font>      <font color="#0000aa">return</font> $ret;
<font color="#909090"><i>  310</i></font>  }
</pre>  
 
</description>
   </item>
   <item>
    <title>Playing with Moose</title>
    <link>http://www.kubat.nl/pages/blogaria/275#275</link>
    <pubDate>Thu, 20 Sep 12 09:36:27 +0200</pubDate>
    <description>
 I've been playing around
with <a href="http://www.catalystframework.org/"
target="_blank">Catalyst</a>, the MVC framework for Perl app servers.
All tutorials and the book <i>The Definitive Guide to Catalyst</i>
work with Moose - so as I'm trying out Catalyst, I decided to dig
deeper into Moose. Here's a tiny introduction.

<h2>So what is Moose?</h2>

Moose is basically a framework, or scaffold, to ease the pain of retyping accessors of Perl classes. Typically, if you have say a class called "Person", you'll have an accessor "firstname" that is both a getter and a setter:

<pre>
  sub firstname {
      my ($self, $firstname) = @_;
      $self->{firstname} = $firstname
	if (defined $firstname);
      return $self->{firstname};
  }
</pre>

Of course you'll have tons of such accessors, for a last name, a
middle name, sex, color of hair, shoe size... Retyping this gets
really bothersome after a while. Perl already has some nice "gadgets"
to simplify this - e.g., AUTOLOAD-ing (see
my <a href="/pages/blogaria/149">blog post</a> on this subject). But
still, Moose is really nicer.

<p/> Then, in standard Perl object lingo, you'll have the preamble of the
class, starting with "use strict / use warnings", and then going into
"use Exporter" and defining all methods that you would like to export.
Moose makes all this really superfluous, just one statement "use
Moose" is all it takes.

<p/> All this, and much more, is <b>greatly</b> simplified when you use
Moose. In addition, Moose offers out of the box roles of your classes,
hooks for pre- and post-modification of object fields, coercion of
values (e.g., string to date), and loads more. Moose really is
complete. But, unfortunately, at a performance cost. Here's an evaluation.

<h2>For example.. invoices</h2>

<p/> I'll illustrate Moose with a tiny program that displays an
invoice, such as illustrated below. There are the following parts to
the invoice:

<ul>
  <li> An invoice has an ID. </li>
  <li> An invoice also has a customer. </li>
  <li> The customer has a name and an address. </li>
  <li> Furthermore, the invoice has a number of invoice lines. </li>
  <li> Each invoice line has a description, a unit price, and a quantity. </li>
  <li> The invoice therefore has a total price. </li>
</ul>

Here's a sample. The invoice ID is 2012-09-17785, the customer is Charlie's Cheeses in Alexandria. There are three invoice lines, concerning Cheddar, Roquefort and Emmentaler. Finally there's the total:
<pre>
                                   I N V O I C E
     
     2012-09-17785
     Charlie's Cheeses
     1415 River Rd., Alexandria, 34557 MN
     
     Description                       Qty    Unit    Subtotal
       Cheddar, 1kg                      2   12.50       25.00
       Roquefort, 100gr                  1    2.35        2.35
       Emmenthaler, 5kg                  3   49.90      149.70
     
     Total:                                             177.05
</pre>

<h2>A Customer</h2>

Let's dive right into the code. Here's a Perl module to handle a
Customer, having a name and an address. The Customer may be
constructed having the name and address right in the call to "new", as in:

<pre>
  my $c = Customer->new(name    => 'Customer name',
                        address => 'Some address');
  print "Customer is called ", $c->name, "\n",
        "and has the address", $c->address, "\n";
</pre>

Alternatively, the fields can be set separately:

<pre>
  my $c = Customer->new;
  $c->name('Customer name');
  $c->address('Some address');
  print "Customer is called ", $c->name, "\n",
        "and has the address", $c->address, "\n";
</pre>

On the left side is a listing with the "standard" Perl class code, a-la Tom's Object Oriented Tutorial (try <i>perldoc perltoot</i> to see it). On the right side is the Moose equivalent.

<table>
  <tr>
    <td width="50%" valign="top">
      <pre>
package Customer;
use strict;
use warnings;

use Carp;
use Exporter;

our @ISA    = qw(Exporter);
our @EXPORT = qw(new name address);

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    my %opt = @_;
    for my $key qw(name address) {
	$self-&gt;{$key} = $opt{$key} if (defined $opt{$key});
    }

    $self;
}

sub name {
    my ($self, $name) = @_;
    $self-&gt;{name} = $name if (defined $name);
    $self-&gt;{name};
}

sub address {
    my ($self, $address) = @_;
    $self-&gt;{address} = $address if (defined $address);
    $self-&gt;{address};
}

1;
      </pre>
    </td>
    <td valign="top">
      <pre>
package Customer;
use Moose;

has 'name'    =&gt; (is =&gt; 'rw', isa =&gt; 'Str');
has 'address' =&gt; (is =&gt; 'rw', isa =&gt; 'Str');

no Moose;
__PACKAGE__-&gt;meta-&gt;make_immutable;
1;	
      </pre>

      Pretty impressive huh? Don't mind the last two lines ("no Moose" etc.). They clean up the scaffolding. Details are in the docs ;-)

      <p> Moose's "has" method basically sets up the internal data fields and the accessor methods. In this example it's instructed to set up an accessor "name", which is read/write (i.e., may be used in the "new" constructor, or in separate methods that override previous values). The type is a "Str", which is of course a string.
    </td>
  </tr>
</table>

<h2> Next, an invoice line </h2>

The next class represents one invoice line, having an item
description, a quantity, and a unit price. Pretty simple. Besides
these accessors, there's also the method "total" that checks that the
necessary fields are there, and then returns the total of the invoice
line.

<p/> Again, left is the Moose-free code, right is the Moose-scaffolded Perl.

<table>
  <tr>
    <td width="50%" valign="top">
      <pre>
package Invoiceline;
use strict;
use warnings;

use Carp;
use Exporter;

our @ISA    = qw(Exporter);
our @EXPORT = qw(new description qty unitprice);

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    my %opt = @_;
    for my $key qw(description qty unitprice) {
	$self-&gt;{$key} = $opt{$key} if (defined $opt{$key});
    }
      
    $self;
}

sub description {
    my ($self, $description) = @_;
    $self-&gt;{description} = $description if (defined $description);
    $self-&gt;{description};
}

sub qty {
    my ($self, $qty) = @_;
    $self-&gt;{qty} = $qty if (defined $qty);
    $self-&gt;{qty};
}

sub unitprice {
    my ($self, $unitprice) = @_;
    $self-&gt;{unitprice} = $unitprice if (defined $unitprice);
    $self-&gt;{unitprice};
}

sub total {
    my $self = shift;
    croak 'No unitprice' unless ($self-&gt;unitprice);
    croak 'No qty'       unless ($self-&gt;qty);
    return $self-&gt;unitprice * $self-&gt;qty;
}

1;
      </pre>
    </td>
    <td valign="top">
      <pre>
package Invoiceline;
use Moose;
use Carp;

has 'description' =&gt; (is =&gt; 'rw', isa =&gt; 'Str');
has 'qty'         =&gt; (is =&gt; 'rw', isa =&gt; 'Int');
has 'unitprice'   =&gt; (is =&gt; 'rw', isa =&gt; 'Num');

sub total {
    my $self = shift;
    croak 'No unitprice' unless ($self-&gt;unitprice);
    croak 'No qty'       unless ($self-&gt;qty);
    return $self-&gt;unitprice * $self-&gt;qty;
}

no Moose;
__PACKAGE__-&gt;meta-&gt;make_immutable;
1;	
      </pre>

      Again, the Moose scaffolding really helps shortening the code.
      The accessors for "description", "qty" and "unitprice" are
      instantiated using just three "has" statements. This really
      makes the code cleaner and saves typing. Regardless of whether
      Moose is used, the Perl package can be extended with any other
      methods you'd like, even coded in the standard "old-fashioned"
      way. That's why the method "total" is identical in both
      listings.

      The call to the Moose method "has" can have many more options,
      such as a default value, a function that's executed after the
      value changes (e.g., for range checks), how a value can be
      coerced from a different type, etc. Moose furthermore supports
      roles. See the docs for more.
      
    </td>
  </tr>
</table>

<h2> The Invoice </h2>

Having done the prework, here's what an invoice is. It must have an
ID, a customer, and invoice lines. I've chosen to implement the
invoice lines as an array of refs to "Invoiceline" objects. There's a
method "invoiceline" that adds one "Invoiceline" object to the array.
Finally there's a method "display" to show the invoice on screen.

<p/> Again, left side is standard code, right side is Moose. The
method "display" is identical in the two versions. Just for the fun of
it, the fields for the customer and the invoice ID may only be set
during construction ("Invoice->new"), but not using the method calls.
This is implemented in the non-Moose code by inspecting the parameters
to "new" and requiring the tags "id" and "customer". In Moose-talk
this is simply done by flagging these accessors as "ro", which is of
course read/only - meaning that the values can be set only during
initialization (object construction).

<table>
  <tr>
    <td width="50%" valign="top">
      <pre>
package Invoice;
use strict;
use warnings;

use Carp;
use Exporter;

our @ISA    = qw(Exporter);
our @EXPORT = qw(new id customer invoicelines invoiceline display);

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    my %opt = @_;
    for my $key qw(id customer) {
	if (defined $opt{$key}) {
	    $self-&gt;{$key} = $opt{$key};
	} else {
	    croak 'No $key option in construction';
	}
    }
    $self-&gt;{invoicelines} = $opt{invoicelines}
      if (defined $opt{invoicelines});
      
    $self;
}

sub id {
    my ($self, $id) = @_;
    $self-&gt;{id} = $id if (defined $id);
    $self-&gt;{id};
}

sub customer {
    my ($self, $customer) = @_;
    $self-&gt;{customer} = $customer if (defined $customer);
    $self-&gt;{customer};
}

sub invoicelines {
    my ($self, $invoicelines) = @_;
    $self-&gt;{invoicelines} = $invoicelines if (defined $invoicelines);
    $self-&gt;{invoicelines};
}

sub invoiceline {
    my ($self, $invoiceline) = @_;
    if (not defined $self-&gt;{invoicelines}) {
	$self-&gt;{invoicelines} = [ $invoiceline ];
    } else {
	push @{ $self-&gt;{invoicelines} }, $invoiceline;
    }
    $self;
}

sub display {
    my $self = shift;

    print
      "\n",
      "                              I N V O I C E\n",
      "\n",
      $self-&gt;id, "\n",
      $self-&gt;customer-&gt;name, "\n",
      $self-&gt;customer-&gt;address, "\n",
      "\n",
      "Description                       Qty    Unit    Subtotal\n";
    my $overall_total = 0;
    for my $l (@{ $self-&gt;invoicelines}) {
	printf "  %-28s %6d   %5.2f  %10.2f\n",
	  $l-&gt;description, $l-&gt;qty, $l-&gt;unitprice, $l-&gt;total;
	$overall_total += $l-&gt;total;
    }
    printf "\nTotal: %50.2f\n\n", $overall_total;

    $self;
}    

1;
      </pre>
    </td>
    <td valign="top">
      <pre>
package Invoice;
use Moose;
use Customer;
use Invoiceline;

has 'id'	      =&gt; (is  =&gt; 'ro', isa =&gt; 'Str');
has 'customer'        =&gt; (is  =&gt; 'ro', isa =&gt; 'Customer');
has 'invoicelines'    =&gt; (is  =&gt; 'rw', isa =&gt; 'ArrayRef[Invoiceline]');

sub invoiceline {
    my ($self, $line) = @_;
    
    if (not $self-&gt;invoicelines) {
	$self-&gt;invoicelines( [$line] );
    } else {
	push @{ $self-&gt;invoicelines }, $line;
    }
    $self;
}

sub display {
    my $self = shift;

    print
      "\n",
      "                              I N V O I C E\n",
      "\n",
      $self-&gt;id, "\n",
      $self-&gt;customer-&gt;name, "\n",
      $self-&gt;customer-&gt;address, "\n",
      "\n",
      "Description                       Qty    Unit    Subtotal\n";
    my $overall_total = 0;
    for my $l (@{ $self-&gt;invoicelines}) {
	printf "  %-28s %6d   %5.2f  %10.2f\n",
	  $l-&gt;description, $l-&gt;qty, $l-&gt;unitprice, $l-&gt;total;
	$overall_total += $l-&gt;total;
    }
    printf "\nTotal: %50.2f\n\n", $overall_total;

    $self;
}    

no Moose;
__PACKAGE__-&gt;meta-&gt;make_immutable;
1;
      </pre>
    </td>
  </tr>
</table>

<h2>The Test Script</h2>

Finally there'a a test script that instantiates two invoices and
displays them. The script of course works with both Moose and
non-Moose package implementations, since the accessors are identical.
Just as an illustration, the second invoice construction is "chained"
in the calls; as in
Invoice->new(...)->invoiceline(...)->invoiceline(...)->display.

<pre>
#!/usr/bin/env perl

use strict;
use warnings;

use Customer;
use Invoiceline;
use Invoice;

my $i =
  Invoice-&gt;new(id       =&gt; '2012-09-17784',
	       customer =&gt; Customer-&gt;new(name    =&gt; 'Bits and Stuff',
					 address =&gt; '1200 Main St., '.
					             'Wright, 77145 TX'));

$i-&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'Nibble',
				 qty         =&gt; 4,
				 unitprice   =&gt; 0.12));
$i-&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'High bit',
				 qty         =&gt; 3,
				 unitprice   =&gt; 0.03));
$i-&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'Low bit',
				 qty         =&gt; 1,
				 unitprice   =&gt; 0.01));
$i-&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'Byte',
				 qty         =&gt; 65536,
				 unitprice   =&gt; 0.18));
$i-&gt;display;


Invoice
  -&gt;new(id =&gt; '2012-09-17785',
	customer =&gt; Customer-&gt;new(name =&gt; 'Charlie\'s Cheeses',
				  address =&gt; '1415 River Rd., Alexandria, '.
				             '34557 MN'))
  -&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'Cheddar, 1kg',
				 qty =&gt; 2,
				 unitprice =&gt; 12.50))
  -&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'Roquefort, 100gr',
				 qty =&gt; 1,
				 unitprice =&gt; 2.35))
  -&gt;invoiceline(Invoiceline-&gt;new(description =&gt; 'Emmenthaler, 5kg',
				 qty =&gt; 3,
				 unitprice =&gt; 49.90))
  -&gt;display;
</pre>

<h2>Evaluation</h2>

So far so good. But how fast is Moose? Unfortunately.. using Moose has
a great impact. Running the non-Moose version a hundred times took me
1.6 seconds on my laptop. the Moose version ran for 27.5 seconds, so
that's 17 times slower.

<p/> Here's my take on it: <i>As a programmer, you do get a lot more
  when using Moose. But the performance is a serious drawback when using
  it for small command-line tools. However, in a once-loaded app server
  environment, such as in Catalyst, it's really worth while. The load
  time is used up just once, and the code becomes much cleaner and
  "safer". So, yeah, I plan on using Moose for bigger projects that
  run in a load-once web container; but not for the daily scripts
  that glue together a Unix system.</i>

<p/>
Comments or remarks as ever
to <a mailto="karel@kubat.nl">karel@kubat.nl</a>. Happy Perl coding!

<hr/>
<img src="/bld/warning.png" class="floatleft"/>
<h2>Update</h2>
Just a day later I received a remark and a question from Eddie: <br/>
<i>Nice post mate. I've never heard of Moose before. <br/>
Did you benchmark Moose code inside an app-server? I'm curious if the
  tremendous overhead is caused by the loading part only or is it
  (partly) a runtime penalty? <br/>
If it is loading-overhead only it is a viable option. Otherwise I
  would hack a little code-generator to generate the boilerplate stuff
  and hand-code the functional parts. Maybe do the functional parts in
  another file and the generator constructs the final class. That way
  you can overload the boilerplate methods if so desired... <br/></i>

<p/> Well let's see. I took one of the above shown Invoice generation
blocks and ran the following test:
<ul>
  <li> I measured the load time </li>
  <li> I measured the excution time of running the Invoice-&gt;new(...)
  call 100.000 times </li>
  <li> I did this with the Moose-scaffolded version and with the plain
  Perl-OO version. </li>
</ul>

And the results are...
<ol>
  <li> The script load time is was 50 times longer when using Moose in
    this example; </li>
  <li> Instantiating a Moose-enhanced class was 2 times longer when
    using Moose. </li>
</ol>

So the penalty is mainly in the load time, which would mean that Moose
is prefectly suitable for an app-server context. The execution which
is 100% slower is I think acceptable; because:
<ul>
  <li> Normally Perl code won't be only Moose-instantiation, there
    will be lots of other tasks (which diminishes the Moose-induced
    performance hit); </li>
  <li> Usually an application will spend most of its time waiting for
    I/O anyway (such as a database or a webservice call), which will
    further mean that the Moose-hit is relatively much smaller; </li>
  <li> Hardware gets faster by the day, so who cares. </li>
</ul>
 
</description>
   </item>
   <item>
    <title>How do you export photos from Adobe Photoshop Elements</title>
    <link>http://www.kubat.nl/pages/blogaria/274#274</link>
    <pubDate>Tue, 28 Aug 12 11:30:55 +0200</pubDate>
    <description>
 <div width="460" class="floatright">
  <i>Figure 1: Elements Organizer "File" dialog</i><br/>
  <img src="/bld/adobe/filemenu.png"/>     <br/> <br/> <br/>

  <i>Figure 2: Copy/Move files: Dialog 1</i><br/>
  <img src="/bld/adobe/movefiles.png"/>    <br/> <br/> <br/>

  <i>Figure 3: Copy/Move files: Dialog 2</i><br/>
  <img src="/bld/adobe/selectusb.png"/>    <br/> <br/> <br/>

  <i>Figure 4: Disk Utility: New Image dialog</i></br/>
  <img src="/bld/adobe/diskutility.png"/>  <br/> <br/> <br/>
</div>

Adobe Photoshop has a workflow-ish organizer called Organizer. This is available on both Windows and Mac.

<h2>The Problem</h2>
However, exporting from the Mac version is a bit of a hassle. Quite a few forums are dedicated to this question - e.g., <a href="http://forums.adobe.com/message/4612740" target="_blank">the Adobe forum</a>, which e.g. states:

<p/>
The question:<br/>
<i><b>How to export photos from Elements Organizer on Mac?</b><br/>
I saw someone asked the same question and it seemed not to be possible with the Mac version. Surely this can't be possible as this must be one of the single most important functions in an Archving system.</i>

<p/>
And the responses: <br/>
<i>
  - The export option from Organizer is only available on Windows. On the Mac you will need to use “Save As” from the Editor or for batch processing File &gt;&gt; Process Multiple Files. <br/>
  - Well so long as the function exists in Mac. But I can't see a "process multiple files" option under "File"? <br/>
  - There is no way to export from organizer on a mac. Adobe's suggestion is to open photos in editor and do a save as. <br/>
  - That's totally mad. Save as? What one by one? Surely this is one of the most fundamental functions in a photo archiving system? And why in windows but not in mac? My standard workflow is import from camera to an archive (eg Organizer or Lightroom), edit, export to folder, ftp to client. If you can't export from Organizer, it means I can't use it. Crazy. <br/>
  - Wow, right. I think that's where my experiment with Elements Organizer stops. Back to Lightroom! Thanks a million! <br/>
</i>

<p/>
Is it really the case that it's <b>impossible</b> to export from the Elements Organizer? Nah... there must be a way.

<h2>The Solution</h2>
Elements Organizer doesn't have an <i>export</i> function in the <i>file</i> menu, but it does have an option <i>copy/move to removable drive</i>. This option in fact does exactly what export should do:

<ul>
  <li> From stacks it will copy the topmost picture, </li>
  <li> When pictures are edited then it will copy the modified version. </li>
</ul>

This option can be used without any problems to export images. The obvious steps are:

<ol>
  <li> Pop a USB drive into your Mac; </li>
  <li> Select the images to export; </li>
  <li> Hit <i>File &gt;&gt; copy/move to removable drive </i> (see Figure 1); </li>
  <li> In the next dialog, make sure that the option <i>Move files</i> is unchecked (see Figure 2); </li>
  <li> In the next dialog select the USB drive as destination (see Figure 3); </li>
  <li> Click <i>done</i> and presto. </li>
</ol>

After that, Elements Organizer will happily fill up your USB drive with the photo's that you selected.

<h2>What if you don't have a USB drive handy?</h2>
It's a weird thing that this exporter only works on external drives, such as USB's, simply refuses to export to a folder on your main (root) drive. Well, nothing's impossible on Unix, right? If you don't have a USB drive handy, you can always create an image, mount it, and export there. Here's how.

<ol>
  <li> Start up the Disk Utility (under Applications / Utilities). </li>
  <li> Click the <i>New Image</i> icon at the top (see Figure 4). </li>
  <li> Select a size that you expect not to exceed, say 500Mb, which should be enough for most exports. </li>
  <li> Hit <i>Create</i>. After this step, the disk will appear as the typical image icon on your desktop, and it will be mounted (i.e., usable).
</ol>

Once you have this image, you can use Elements Organizer to export your files into this location; he dialog <i>Destination Settings</i> will show it. You don't have to create this image drive for every export. Just create it once, and re-use it every time you need to export your photos.

<h2>That's all!</h2>
If you have questions / remarks, don't hesitate to mail me at <a href="mailto:karel@kubat.nl">karel@kubat.nl</a>. Happy exporting!
 
</description>
   </item>
   <item>
    <title>Security hole at the Empire State Building</title>
    <link>http://www.kubat.nl/pages/blogaria/273#273</link>
    <pubDate>Tue, 21 Aug 12 20:59:28 +0200</pubDate>
    <description>
 <img src="/bld/ESB/ESB-building.png" class="floatright"/>

<p/>
This year's holiday included a visit to New York City. The kids were there for the first time, so hey, what can you do. You visit all the tourist stuff, including the Empire State Building. This story is about a little oopsie I had there by bringing a knife - and a big oopsie the security implementation has.

<p/>
Once you enter the Empire State Building, you pass through security; similar to musea and the airport. You have to remove your belt (which I dutifully did), put your mobile phone and wallet into a basket (which I dutifully did), put your bag and basket on the conveyor belt for the X-ray machine (which I dutifully did), and pass through the metal detector gate (which I dutifully did). Lo and behold, no beeps, I am metal-free. On the other side of the gate I picked up the stuff from my basket, put on my shoes, and stuck the belt in my pants. Then I proceeded to wait for my bag.

<p/> Security at the Empire State Building checks for the same stuff that the TSA dislikes: weapons, guns, what you have, and even tripods. They don't allow photographers to bring their tripod along. Maybe they think that photographers are prone to threatening airplane crews. Maybe they're afraid that someone will try to crash the Empire State Building into the White House. Anyway, I didn't have a tripod with me, so who cares?

<p/>
(Deep voice) Sir, is this your bag? <br/>
(Me) Yes, it is. <br/>
(Deep voice) Sir, it appears you have a knife in your bag. <br/>

<p/>
<center>
  <img src="/bld/ESB/ESB-knife.jpg"/>
</center>

<p/> 
At this point I thought, oh crap. I had my camping knife with me, because it doubles as sandwich-maker. I'd forgotten to take it out of my bag. Fortunately, since the Empire State Building isn't an airport, I could leave the knife downstairs to be picked up later. Whee! Saved. I'd have hated to loose the knife, it's a really fine piece of equipment. So I proceeded to put the knife in a numbered plastic bag, which was then dutifully sealed by the security personnel. The top of the bag, which had the same number stencilled on it, was ripped off and given to me, by way of receipt. Great! The entire family filed towards the elevators to enjoy the view. It was a particularly clear day.

<p/>
On the way back we filed into the lobby to exit to the street. I however still had to pick up my knife, so I re-entered the line towards security. I didn't want to wait that long, so as soon as I saw a security guy, I showed my receipt. "Right this way" he said, and I bypassed the line. I was instructed to "talk to that guy over there, behind the metal detectors". So, still waving my receipt, I went towards the detector gates, and I was let through - without removing my shoes or belt, and while holding my bag. The detector gate went berserk, it beeped like crazy and flashed all colors. The security people however didn't mind, because I was just picking up stuff. So they let me through. I then talked to the person who was pointed out to me, who took my receipt and handed over my knife. I put the knife in my bag and looked around for the exit (remember, I was now again in the line towards the ascending escalators). The security guy noticed that I was looking for the way out, so in a helpful mood he informed me: "You can exit over there, through those double doors". I thanked him and went towards the exit.

<p/> I had to wiggle through 3 lines towards the ascending elevators to get to the exit doors, then I was at the exit towards the lobby. But before leaving the security area, I decided to talk to the guy who had given me the knife. So I went back (wiggling through 3 lines of people again), and said, "Hey, just one more thing. I got here through a beeping metal detector, I could have loads of stuff in my bag, you just handed me my knife, and I could just as well go to the ascending escalators, instead of towards the exit. Isn't that weird?" He looked at me for about 30 seconds, and the said, "Yeah, well, we're just following the rules here." I politely thanked him and headed towards the exit doors, and proceeded to the lobby and the street.

<p/>
The moral of the story?
<ul>
  <li> A real attacker would have a mate standing in the lobby with guns, bombs and what you have, just waiting. </li>
  <li> He'd then go through security and would make sure that he'd have a knife or a pair of scissors or a tripod, which would be left in a sealed bag in the security area. </li>
  <li> After some time the attacker would exit to the lobby, get his mate's bag of tricks, and proceed to the security area, while waving his receipt. </li>
  <li> In the security area he'd pick up his tripod or whatever, and go to the ascending escalators. </li>
  <li> Voila. </li>
</ul>

So much for following procedures without ever thinking....
 
</description>
   </item>
   <item>
    <title>Matrix Sunglasses</title>
    <link>http://www.kubat.nl/pages/blogaria/272#272</link>
    <pubDate>Sun, 15 Jul 12 19:34:55 +0200</pubDate>
    <description>
 <table width="100%">
  <tr>
    <td valign="top">
      Some time ago I ordered sunglasses from <a href="http://www.matrix2sunglasses.com/" target="_blank">matrix2sunglasses.com</a>. My son had a pair and of course I had to follow suit. They are the "Morpheus" ones, those that sit on your nose. From the description: <i>"Over the years there have been many attempts at recreating the original Blinde design, but most were of poor quality.  The M.2. Morpheus however is simply outstanding. High quality 10 base polycarbonate lenses provide optical clarity and the finish is superb whilst we upgraded the Pince-Nez device along with silicone nosepads.  All of Morpheus sunglasses offer UV400 protection."</i>

      <p/> I received them a few days ago. Beautiful weather outside, time for a ride and a roadtest.

      <p/> The good thing about the Pince-Nez construction is that the glasses fit wonderfully inside a motorcycle helmet. I've tried to wear my standard ones under the helmet, but after about half an hour the pressure of the ear pieces gets really annoying. I guess that my helmet just fits too well around my head ;-) These sunglasses solve the problem.

      <p/>
      <b>Test Results:</b><br/>
      <ul>
	<li> The sunglasses sit pretty solidly on your nose, they don't wiggle or fall off. I had the visor open, and at a speed of say 80kmh there were no problems at all. </li>
	<li> The wear is very comfy. The silicone pads are big enough to prevent pinching, and the shades are really very light. </li>
	<li> The optics are pretty good, there is absolutely no distortion of the image, not even near the sides of the shades. The color is good (green with a hint of brown). I'd prefer polarized shades, but I guess that the necessity of this lightweight model doesn't allow for real glass. Plus I might not want real glass inside my helmet anyway, incase of crashes. </li>
	<li> A real bonus is that you can remove or put on these shades without removing your helmet. Just open the visor, and they're accessible. </li>
	<li> All in all? Very comfy and handy for a helmet situation. </li>
	<li> They probably won't work if you have a crooked nose 'cause it's been broken. </li>
      </ul>
      
    </td>
    <td width="500" valign="top">
      <img src="/bld/MatrixSunglasses/Glasses1.jpg"/>
      <br/> <p/> <br/>
      <img src="/bld/MatrixSunglasses/Glasses2.jpg"/>
      <br/> <p/> <br/>
      <img src="/bld/MatrixSunglasses/Wearing.jpg"/>
    </td>
  </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Two Morgans</title>
    <link>http://www.kubat.nl/pages/blogaria/271#271</link>
    <pubDate>Thu, 12 Jul 12 20:20:07 +0200</pubDate>
    <description>
 Today, while on the bike near Schiphol Airport, I encountered two British Morgan-8 cars. Real fun to see in their natural habitat. Here are some pics.

<p/>

<center>
  <img src="/bld/morgan/IMG_1322.JPG"/> <br/>
  <i>The logo..</i>
  <p/>&nbsp;<p/>

  <img src="/bld/morgan/IMG_1318.JPG"/> <br/>
  <i>Front view</i>
  <p/>&nbsp;<p/>

  <img src="/bld/morgan/IMG_1319.JPG"/> <br/>
  <i>Front and Side</i>
  <p/>&nbsp;<p/>

  <img src="/bld/morgan/IMG_1320.JPG"/> <br/>
  <i>The black one</i>
  <p/>&nbsp;<p/>

  <img src="/bld/morgan/IMG_1321.JPG"/> <br/>
  <i>Luggage wrapped in a Union Jack, lol!</i>
</center>  
 
</description>
   </item>
   <item>
    <title>Review of the BMW R1200RT Motorbike</title>
    <link>http://www.kubat.nl/pages/blogaria/270#270</link>
    <pubDate>Thu, 12 Jul 12 20:20:07 +0200</pubDate>
    <description>
 My own BMW K1200GT is in the shop, and since yesterday I'm riding a
R1200RT - kindly provided by the garage. It's fun to ride a different
bike, to get a feel for it. But the R series is so radically
different, that I decided to write up what I think are striking
differences between otherwise comparable tour bikes.

<p/>
<b>Similarities</b><br/>
First of all, why are the R1200RT and the K1200GT somewhat similar?
<ul>
  <li> Both are built for longer distances on the road; real "tour bikes". </li>
  <li> Both are pretty heavy, well over 250kg, but capable of
    supporting the driver, a passenger and luggage. </li> 
  <li> Both have a top speed of well over 200kmh. </li>
  <li> Both are built to minimize maintenance and maximize safety;
    e.g., both have a cardan shaft that drives the wheel, both have
    ABS. </li> 
</ul>

<p/>
<center>
  <img src="/bld/r1200rt/IMG_1324.JPG"/>
  <img src="/bld/r1200rt/IMG_1325.JPG"/> <br/>
  <i>The red R1200RT. Good looking though.</i>
</center>
<p/>

<p/>
<b>First impressions</b><br/>
The biggest difference is that the K series has four cylinders, while
the R series has two, in a boxer-configuration. The volume on both
bikes is 1200cc, so that's pretty comparable. The boxer engine looks
kinda sexier though, a bit meaner and tougher. The gasoline tank is a
bit wider, there's a neat aluminium rail over it with clamps for a
bag. The dash is very similar to my K1200GT; same board computer and
stuff (though this R didn't have cruise control and seat heating,
which are extra's). I was happy to see the switches for the turn
indicators at the "right" places where I expect them: thumb paddles
left and right, instead of the Japanese-inspired one-switch on the
left handle bar. Newer BMW's have the one-switch approach though,
which I think is not that great. Sad. 

<p/>
<center>
  <img src="/bld/r1200rt/IMG_1326.JPG"/> <br/>
  <i>Mean-looking gas tank.</i>
</center>
<p/>

<p/>
<center>
  <img src="/bld/r1200rt/IMG_1327.JPG"/> <br/>
  <i>Standard BMW dash with turn indicator switches left AND right, <br/>
    handle bar heater switch on the right side, <br/>
    electrical windscreen switch also right.</i>
</center>
<p/>

<b>Windscreen</b><br/>
Another interesting fact is that the windscreen of the K1200 absorbs
and deflects much more rain. On the K1200 you feel as if you're in an
air bubble and the droplets pass by. The R1200 has a different
configuration of rearview mirrors (under the handle bars) and when the
windscreen is tilted upward, there's a fairly large gap where the rain
hits your gloves, sleeves and jacket. You really get more wet. 

<p/>
<center>
  <img src="/bld/r1200rt/IMG_1328.JPG"/> <br/>
  <i>With the windscreen tilted upwards, you get wet.</i>
</center>
<p/>

<p/>
<b>Performance</b><br/>
The K1200 spits out a neat 160hp, divided over normally up to 10.000rpm (10.000 to 12.000 being "in the red"). The R stops at 110hp, at up to 8.000rpm (8.000 - 10.000 is "red"). All in all, the K is way more sporty, and yes, handles much better. It's a great sprinter, it keeps you on your toes, and gives a ton of fun while riding it. This R1200 feels sluggish, the steering seems more difficult (despite the fact that it's 20kg lighter!), it doesn't rev. 

<p/>
<b>Summary</b><br/>
I remember driving a VW Golf Diesel for the first time, must be 20 years ago or more. I was overwhelmed by the same emotion when riding the R1200RT. Sluggish, slow, you open up the gas and it goes "prrrrrrrrrrrrrr" instead of making you go "Whoa! Jeez!". Basically riding the R1200RT is like driving a truck.

<p/>
<center>
  <table class="box">
    <tr>
      <th class="box">Subject</th>
      <th class="box">R1200RT</th>
      <th class="box">K1200GT</th>
    </tr>
    <tr>
      <td>Built for?</td>
      <td>Touring bike, for long distances on the road</td>
      <td>Same here</td>
    </tr>
    <tr>
      <td>cc's?</td>
      <td>1200cc</td>
      <td>1200cc</td>
    </tr>
    <tr>
      <td>Engine?</td>
      <td>Two cylinders in a boxer configuration</td>
      <td>Four cylinders in line</td>
    </tr>
    <tr>
      <td>Hp?</td>
      <td>110hp</td>
      <td>160hp</td>
    </tr>
    <tr>
      <td>Looks?</td>
      <td>Looks like a bad mofo</td>
      <td>Looks like it's built for speed</td>
    </tr>
    <tr>
      <td>Wind while driving?</td>
      <td>Windscreen tilts up, great for avoiding wind</td>
      <td>Same here</td>
    </tr>
    <tr>
      <td>How about rain?</td>
      <td>Windscreen deflects some rain but you still get wet</td>
      <td>Windscreen creates a cool bubble to keep you dry</td>
    </tr>
    <tr>
      <td>Style?</td>
      <td>Easy going carefree riding</td>
      <td>Keeps you on your toes</td>
    </tr>
    <tr>
      <td>When you open up the throttle?</td>
      <td>Engine goes prrrrrrrrr</td>
      <td>You go prrrrrrrr as you shit your pants</td>
    </tr>
    <tr>
      <td>Audience?</td>
      <td>Suggested for leisure and for the elderly</td>
      <td>Suggested for bikers</td>
    </tr>
  </table>
</center>

<p/> I remember someone saying once that BMW bikers are basically in
one of two camps, the K riders and the R riders. Guess I'm a K guy.
 
</description>
   </item>
   <item>
    <title>Passwords: maak het hackers moeilijk</title>
    <link>http://www.kubat.nl/pages/blogaria/269#269</link>
    <pubDate>Wed, 13 Jun 12 19:40:12 +0200</pubDate>
    <description>
 Wil je 't weten? Lees Annemieke's blog op
<a href="http://vrouwen-ondernemen.nl/Columns/Columns/tabid/191/ArticleId/266/Passwords-maak-het-hackers-moeilijk-266.aspx"
   target="_blank">vrouwen-ondernemen.nl</a>.  Het origineel staat op 
   <a href="http://www.annemoves.com/AM/blog/passwords-maak-het-hackers-moeilijk"
   target="_blank">annemoves.com</a> met meer 'stuff' van Annemieke.
 
</description>
   </item>
   <item>
    <title>Mijndomein foutje</title>
    <link>http://www.kubat.nl/pages/blogaria/268#268</link>
    <pubDate>Wed, 13 Jun 12 19:35:21 +0200</pubDate>
    <description>
 [Dutch entry] Laatst claimde ik een domeinnaam bij <a href="http://www.mijndomein.nl" target="_blank">mijndomein.nl</a>. Na registratie kreeg ik een bevestigingsmail. Tot zover niks mis mee. 't Mailtje is hieronder weergegeven. Ra ra wat is er mis mee? (Sommige namen en termen zijn in het plaatje overschreven door XXXXX).

<p/>
<center>
  <img src="/bld/mijndomein-mail.png"/>
</center>

<p/>
Weet je 't al? <i>Het wachtwoord wordt in de mail genoemd. Grote no-no!</i> Dit is fout om twee redenenen:

<ol>
  <li> Het wachtwoord staat in een e-mail bericht. Iedereen die mijn mail ziet, ziet dus mijn wachtwoord bij mijndomein.nl. </li>
  <li> Mijndomein.nl heeft mijn wachtwoord in <i>plain text</i>. Anders zouden ze het immers niet in de mail kunnen plakken! Is niet goed. Ze zouden 't wachtwoord in moeten omrekenen naar een "salted hash" en dat opslaan, en 't plain-text wachtwoord moeten vergeten. Want, <a href="/pages/blogaria/53#53">wat je niet hebt, kan ook niet gejat worden</a>. </li>
</ol>

Kortom, in 't mailtje zou hooguit moeten staan: "Wachtwoord vergeten? Klik hier voor support."
 
</description>
   </item>
   <item>
    <title>YOLNT</title>
    <link>http://www.kubat.nl/pages/blogaria/267#267</link>
    <pubDate>Thu, 07 Jun 12 20:27:34 +0200</pubDate>
    <description>
 <center>
  <img src="/bld/yolnt/YOLNT.jpg"/>

  <p/>

  <i>
    YOLO: slang phrase used by morons right before doing <br/>
    something dumb that will probably kill them or <br/>
    give them herpes
  </i>
  
</center>

 
</description>
   </item>
   <item>
    <title>Human Origins</title>
    <link>http://www.kubat.nl/pages/blogaria/266#266</link>
    <pubDate>Wed, 06 Jun 12 20:35:39 +0200</pubDate>
    <description>
 <img src="/bld/HumanOrigins.gif" class="floatright"/>
Seen today:

<ul>
  <li> 46% of USA citizens think that God created humans in the last 10.000 years or so; </li>
  <li> 32% think that humans evolved with God's help; </li>
  <li> 15% think that humans evolved without divine intervention.</li>
</ul>

And that was what, err, a developed country? For completeness, <a
href="http://www.gallup.com/poll/155003/Hold-Creationist-View-Human-Origins.aspx"
target="_blank">here</a> is the source. According to the description,
<i>"results for this USA Today/Gallup poll are based on telephone
interviews conducted May 10-13, 2012, with a random sample of 1,012
adults, aged 18 and older, living in all 50 U.S. states and the
District of Columbia. For results based on the total sample of
national adults, one can say with 95% confidence that the maximum
margin of sampling error is ±4 percentage points."</i>

<p/> Purely coincidentally,
<a href="http://www.usatoday.com/news/opinion/forum/story/2012-06-03/science-math-education-us-schools/55363868/1"
   target="_blank">USA Today</a> reports on the fact that historically
   the average USA student was always mediocre at best when compared
   to other countries. Nevertheless, the USA has a long tradition of
   innovation - so obviously there's quite a gap between the average
   and the top. Interesting.
 
</description>
   </item>
   <item>
    <title>Me on Facebook</title>
    <link>http://www.kubat.nl/pages/blogaria/265#265</link>
    <pubDate>Wed, 30 May 12 15:55:18 +0200</pubDate>
    <description>
 <img src="/bld/MeOnFacebook.png" class="floatright"/>
Oh wonder, Facebook feeds me personal ads. So this is me:
<ul>
  <li> I play simplistic games, </li>
  <li> I am a sucker for overprized designer stuff, </li>
  <li> I am on the lookout for females, </li>
  <li> My prostate needs an overhaul. </li>
</ul>
Thanks, Facebook.
 
</description>
   </item>
   <item>
    <title>Voluntary Layoffs</title>
    <link>http://www.kubat.nl/pages/blogaria/264#264</link>
    <pubDate>Thu, 17 May 12 01:25:58 +0200</pubDate>
    <description>
 Here's a good laugh. Societ&eacute; Generale has offered a voluntary layoff
programme to its employees. Now they had to limit the programme -
because too many people <i>want to leave</i>.

<p/> More lols at
<a href="http://hereisthecity.com/2012/05/16/top-firm-to-limit-voluntary-layoffs-as-too-many-want-to-leave/"
   target="_blank">hereisthecity.com</a>. Thanks, HvE, for showing
this to me :)
 
</description>
   </item>
   <item>
    <title>RBS Bike Tour</title>
    <link>http://www.kubat.nl/pages/blogaria/263#263</link>
    <pubDate>Mon, 07 May 12 20:41:54 +0200</pubDate>
    <description>
 For all RBS colleagues who have a bike and want to go for a ride:
please visit <a href="/pages/tour">the tour page</a>!
<p/>
<img src="/bld/tour/BMW-small.png"/>
<p/>

 
</description>
   </item>
   <item>
    <title>Room with a view</title>
    <link>http://www.kubat.nl/pages/blogaria/262#262</link>
    <pubDate>Fri, 27 Apr 12 21:41:00 +0200</pubDate>
    <description>
 <center>
  <img src="/bld/drawings/RoomWithAView.jpg"/>
</center>

<p/>
Yup, I have a new Wacom Intuos tablet ;-)
 
</description>
   </item>
   <item>
    <title>Browser cookies and Javascript revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/261#261</link>
    <pubDate>Fri, 27 Apr 12 21:41:00 +0200</pubDate>
    <description>
 I wrote <a href="/blogaria/199">before</a> about cookies and Javascript. Recently I had to improve the Javascript library, I needed to "auto-guess" cookie domains and I had to supply a meaningful value for the cookie path. So here's a newer and better version:

<ul>
  <li> The domain is defined as the last two "words" of the domain that the browser is accessing. So if the browser is pointing at say my.secure.website.org, then the domain <i>.website.org</i> is used. </li>
  <li> The cookie path is set to / for all operations. </li>
</ul>

<p/>
The entire interface as described in my <a href="/blogaria/199">previous</a> post still holds. But I updated the file <a href="/cookiesjs/cookies.js">cookies.js</a>. As ever, if you have remarks, let me know at <a href="mailto:karel@kubat.nl">karel@kubat.nl</a>.  
 
</description>
   </item>
   <item>
    <title>Schrodingers Cat</title>
    <link>http://www.kubat.nl/pages/blogaria/260#260</link>
    <pubDate>Fri, 17 Feb 12 09:29:26 +0100</pubDate>
    <description>
 By Michelle Marie, <a href="https://plus.google.com/u/0/114618043230336563405/posts" target="_blank">on Google+</a>:

<p/>

<center>
  <img src="/bld/schrodingers-cat-is-alive-dead.jpeg"/>
</center>
 
</description>
   </item>
   <item>
    <title>KPN heeft problemen</title>
    <link>http://www.kubat.nl/pages/blogaria/259#259</link>
    <pubDate>Fri, 17 Feb 12 09:58:53 +0100</pubDate>
    <description>
 <div width="350" class="box" style="float:right; width:320px">
  <b>[2012-02-17] Update</b><br/>
  KPN heeft de mailgebruikers post gestuurd. Gebruikersnaam <b>en</b>
  wachtwoord in	dezelfde brief. Pffff... Lees meer op
  <a href="http://www.nu.nl/internet/2743106/kpn-stuurt-wachtwoord-en-mailadres-in-brief.html"
  target="_blank">nu.nl</a>.
</div>

Met dank aan <a href="https://twitter.com/#!/AnnemiekeMeibor"
		target="_blank">#Annemieke on Twitter</a>:
KPN heeft echt wel problemen. Ze zijn gehackt, de hackers verschaften
zich toegang tot data, die hebben ze misschien gekopieerd, da's dus misschien
allemaal openbaar, balen.

<p/>
<div class="important">
  <b>Fout 1:</b> Ze hadden gebruikersnamen en <i>plain text
    passwords</i> op hun systeem staan. Dat is nalatig, als je qua
    security jezelf serieus neemt, dan doe je zo iets niet.
    Wachtwoorden moet je <b>altijd</b> hashen en dan opslaan, en dan
    nog, moet je een "salt" gebruiken zodat dezelfde wachtwoorden
    altijd een andere hash opleveren. Dit wisten we al rond 1970 toen
    Unix werd ontworpen. Stom stom stom!
</div>

<p/>
Maar ja, dus, hoe nu verder. Je gebruikers zullen toch een keer hun
password moeten wijzigen om misbruik te voorkomen. Snap ik. Bovendien,
de oude wachtwoorden kun je niet meer vertrouwen, dus bij de
password-reset heeft het geen zin om naar het oude wachtwoord te
vragen. Snap ik. Dus moet je een andere methode verzinnen. Snap ik
ook.

<p/> Dus wat heeft KPN verzonnen? Vanaf het IP adres dat bij je
Internet abonnement hoort, kun je makkelijk je wachtwoord wijzigen.
Dan weet de KPN namelijk dat je 't echt bent en niet iemand die je
username/password combinatie kent en in China zit. Snap ik. Dit is op
zich een goed idee, behalve dat alleen je IP adres onvoldoende is om
je te identificeren. Dus wat willen ze nog meer weten om er zeker van
te zijn dat jij 't bent? <i>De laatste 3 cijfers van je rekeningnummer
waarmee je je KPN abonnement betaalt.</i> Niet verkeerd bedacht, snap
ik. Maar nou komt 't:

<ul>
  <li> Je mag (vanaf je IP adres) net zovaak de
    laatste 3 cijfers van je bankrekeningnummer intikken als je wilt;
    totdat je 't invoerscherm krijgt voor een nieuw wachtwoord. </li>
  <li> Er wordt verder niks gevraagd (niet "de meisjesnaam van mijn
    moeder", of "mijn favoriete kleur", "hoeveel neuzen heb ik", etc.</li>
</ul>

<p/>
<div class="important">
  <b>Fout 2:</b> De password-reset applicatie van KPN is lek. Door een
  heel simpele brute force attack ben je zo binnen. Je hoeft alleen
  maar "op het IP adres" te zitten van een KPN klant, en binnen een
  paar minuten heb je toegang tot zijn/haar e-mail account. Je hoeft
  alleen maar als laatste cijfers 000 tot en met 999 proberen.
</div>

<p/> Kortom, hier is niet goed over nagedacht. Ik kan me best
voorstellen hoe dat ging. De Customer Intimacy &amp; Service Delivery
Manager (Voorman Klantenbalie) uitte de zorg dat al die bellende KPN
klanten die per telefoon hun wachtwoord gereset willen hebben, het
hele callcenter zullen platleggen. Zijn direct leidinggevende, nl. de
Customer Services Portfolio Manager (Chef Klantenbalie), zou wellicht
zijn bonus mislopen als de gemiddelde wachttijd zou toenemen. Hij
heeft daarom contact opgenomen met de Technology Services Portfolio
Manager (Chef Technisch Beheer) en het probleem voorgelegd - er moest
snel iets komen dat zo "foolproof" was dat zelfs z'n eigen oma ermee
uit de voeten kon. "Ja maar security dan?", vroeg een onschuldige
voorbijgaande ontwerper. "Niks ervan, we gaan voor full customer
satisfaction en empowerment!", zei 't baasje, en dacht, ook voor m'n
bonus. Et voila!

<p/>

En er hoefde maar een kleinigheid bij om 't geheel wel veilig te
maken. Na drie keer verkeerde invoer lock out....

<p/> (En ja, ik heb dumps van de HTTP requests, naar welke URL de POST
moet om een reset te proberen met drie cijfertjes, wat de server
terugstuurt als 't niet lukt, wat de server terugstuurt als 't wel
lukt, en een scriptje dat dat doet. Maar die post ik maar niet. Voor
je 't weet komen mensen op 't idee om te gaan wardriven om iemands
mail te hacken.)
 
</description>
   </item>
   <item>
    <title>Memebase forever</title>
    <link>http://www.kubat.nl/pages/blogaria/258#258</link>
    <pubDate>Thu, 12 Jan 12 23:11:49 +0100</pubDate>
    <description>
 If you like <a href="http://www.memebase.com/"
	       target="_blank">memebase</a>, here's a cool loop.
Brilliantly done!

<p/>
<center>
  <img src="/bld/memebase.gif"/>
</center>
 
</description>
   </item>
   <item>
    <title>Strange squares</title>
    <link>http://www.kubat.nl/pages/blogaria/257#257</link>
    <pubDate>Wed, 11 Jan 12 15:59:24 +0100</pubDate>
    <description>
 Did you know that in the range 1..100 the numbers 41, 42, 43, 44, 45,
46, 54, 55, 56, 57, 58 and have the following in common:

<p/>

<ul>
  <li> When you subtract 25 from the number, you get two digits. We'll
    consider those as the first half of a number. </li>

  <li> When you subtract the number from 50, and square that, you also
  get two digits. We'll consider those as the second half of a
  number. </li>

  <li> The new number (with the left 2 digits and the right 2 digits)
  is the square of what we started with, so the square of 41, 42, 43,
  and so on. </li>

</ul>

For example try 44.

<ul>
  <li> 44 - 25 = <b>19</b> </li>
  <li> 50 - 44 = 6, and 6 x 6 = <b>36</b> </li>
  <li> <b>1936</b> = 44 x 44 </li>
</ul>

<p/> This can of course be easily deduced. First, for every x we require that
<center>
  100(x - 25) + (50 - x)<sup>2</sup> = x<sup>2</sup>
</center>

<p/> This isn't very helpful, it holds true for every imaginable
number of x ;-) <br/>

But second, we also want that (x - 25) has two digits, and that (50 -
x)<sup>2</sup> has two digits, so:

<center>
  (a) 10 &le; (x - 25) &le; 99 <br/>
  (b) 10 &le; (50 - x)<sup>2</sup> &le; 99 <br/>
</center>

<p/>
From (a) it follows that 35 &le; x &le; 99; from (b) it follows that:
<center>
  (b1) x<sup>2</sup> - 100x + 2500 &ge; 10 <br/>
  x<sup>2</sup> - 100x + 2490 &ge; 0 <br/>
  x &le; 46.83 or x &ge; 53.16 <br/>
  <br/>
  (b2) x<sup>2</sup> - 100x + 2500 &le; 99 <br/>
  x<sup>2</sup> - 100x + 2401 &le; 0 <br/>
  x &ge; 40.05 and x &le; 59.94 <br/>
  <br/>
</center>

So overall,
<center>
  40.05 &le; x &le; 46.83 or 53.16 &le; x &le; 59.94
</center>
or with integers
<center>
  41 &le; x &le; 46 or 54 &le; x &le; 59
</center>

<p/> Still, nice doodling on a rainy morning. Oh, and of course the checker:
<pre>
use strict;

for my $n (1..100) {
    my $sq = $n * $n;
    next if (length($sq) != 4);

    my $left  = $n - 25;
    my $right = (50 - $n) * (50 - $n);

    print("$n -> $sq\n") if ("$left$right" == $sq);
}
</pre>
 
</description>
   </item>
   <item>
    <title>TVV Ondernemingsportaalnl.com zuigt ezel</title>
    <link>http://www.kubat.nl/pages/blogaria/256#256</link>
    <pubDate>Thu, 22 Dec 11 18:46:05 +0100</pubDate>
    <description>
 [Dutch] Tsja, het jaar is alweer bijna om. Je krijgt zo nog 'es wat in de bus. Deze keer onder andere een indrukwekkende envelop, belangrijk, indien onbestelbaar terug afzender. Wat zit er in? Mijn onderneming zou zich bekend moeten maken met het BTW nummer, ter identificatie, voor een ondernemingsportaal. Kijk, dat ziet er toch vertrouwenwekkend uit? En via www.ondernemingsportaal-nl.com kun je kostenloos je gegevens actualiseren. Fijn!

<p/>
<center>
  <img src="/bld/TVV01.png"/>
  <img src="/bld/TVV02.png"/>
</center>

<p/>

En dan de rest natuurlijk. Onvermijdelijk:

<p/>

<center>
  <img src="/bld/TVV03.jpg"/>
</center>

<p/>

Ja hoor, jaarlijks wordt 975 euro in rekening gebracht voor die vermelding. Ik ga 't formulier niet terugsturen. Maar ik heb wel een antwoord: <b>ondernemingsportaal-nl.com, geregistreerd door TVV Tele Verzeichnis Verlag GmbH, Borsteler Chaussee 85-99a, te 22453 Hamburg DE, geregistreerd door Wulf Lohmeyer, tel. +49405148490, bereikbaar als admin@tvv-verlag.com: Jullie zijn een stel ranzige colporteurs en oplichters. Jullie zuigen ezel.</b>
 
</description>
   </item>
   <item>
    <title>Dilbert vs Skype</title>
    <link>http://www.kubat.nl/pages/blogaria/255#255</link>
    <pubDate>Thu, 08 Dec 11 13:24:29 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/Dilbert-and-Skype.png"/>
  <p/>
  Why do I feel this way each day when commuting? <br/>
  (See more
  at <a href="http://dilbert.com/strips/comic/2011-12-08/"
	target="_blank">dilbert.com</a>)  
</center>
 
</description>
   </item>
   <item>
    <title>The uncanny resilience of bulshytt</title>
    <link>http://www.kubat.nl/pages/blogaria/254#254</link>
    <pubDate>Tue, 29 Nov 11 12:23:18 +0100</pubDate>
    <description>
 <i>"It is inherent in the mentality of bulshytt-talkers they are more
  prone than anyone else to taking offense (or pretending to) when
  their bulshytt is pointed out to them. This places the observer
  in a nearly impossible position. One is forced either to use this
  "offensive" word and be deemed a disagreeable person and as such
  excluded from polite discourse, or to say the same thing in a
  different way, which means becoming a purveyor of bulshytt oneself and
  thereby lending strength to what one is trying to attack. The latter
  quality probably explains the uncanny stability and resiliency of
  bulshytt."</i>

<p/>
(From Neil Stephenons's Anathem. One of my favorite quotes in the
book.)
 
</description>
   </item>
   <item>
    <title>Another silly Trojan attempt</title>
    <link>http://www.kubat.nl/pages/blogaria/253#253</link>
    <pubDate>Wed, 23 Nov 11 13:29:30 +0100</pubDate>
    <description>
 Apparently it makes sense to send Dutch e-mails now that entice you to run an executable on your system. Received today:

<p/>

<center>
  <img src="/bld/DutchTrojanAttempt.png"/>
</center>

<p/>

Guess what you get when you download the zip. Here's the listing:

<p/>

<center>
  <img src="/bld/DutchTrojanZip.png"/>
</center>

<p/>

LOL! Update.pdf___________.exe. Who still falls for that? Are those people even too lame to craft a malicious PDF?
 
</description>
   </item>
   <item>
    <title>ACTA is coming our way</title>
    <link>http://www.kubat.nl/pages/blogaria/252#252</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  
  <iframe width="560" height="315"
	  src="https://www.youtube-nocookie.com/embed/nh3RRngVF5I?rel=0"
	  frameborder="0" allowfullscreen></iframe>
  <p/>

  Read more about ACTA at <a href="http://lqdn.fr/ACTA"
			     target="blank">http://lqdn.fr/ACTA</a>.
</center>

 
</description>
   </item>
   <item>
    <title>Burgernet in the Netherlands</title>
    <link>http://www.kubat.nl/pages/blogaria/251#251</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I received a weird letter from the the mayor. He wants me to become
member of <i>Burgernet</i>, a civilian watch program. Basically you
sign up, and you then at times receive an SMS message to be on the
lookout for a lost child, someone who's wanted, and what not. Oh and
golly, in case you know of other people who might want to join, you're
invited to register them too.

<p/>

This just smells bad. For one, if you get amateur security personnel,
you'll get amateur security (I didn't think of this,
<a href="http://www.schneier.com/" target="_blank">Bruce Schneier</a>
did).

<p/>

Then there's also that I lived in society where individuals where
encouraged to report on others. And many did, because it got them
small favors. All this reminds me of Eastern Germany... according to
<a href="http://en.wikipedia.org/wiki/Stasi"
   target="_blank">wikipedia</a>:
<i>Between 1950 and 1989, the Stasi
  employed a total of 274,000 people [...] In 1989, the Stasi
  employed 91,015 persons full time, [...] along with 173,081
  unofficial informants inside GDR and 1,553 informants in West
  Germany. In terms of the identity of inoffizielle Mitarbeiter (IMs)
  Stasi informants, by 1995, 174,000 had been identified, which
  approximated 2.5% of East Germany's population between the ages of
  18 and 60. 10,000 IMs were under 18 years of age.
  [...] <b>Informants were made to feel important, given material or
    social incentives, and were imbued with a sense of adventure, </b>
  and only around 7.7%, according to official figures, were coerced
  into cooperating. [...] A large number of Stasi informants were
  trolley conductors, janitors, doctors, nurses and teachers.</i>

<p/>

Guess I'm not joining Burgernet.

<center>
  <img src="/bld/burgernet1-small.jpg"/>
  <img src="/bld/burgernet2-small.jpg"/>
</center>
 
 
</description>
   </item>
   <item>
    <title>Facepalm art</title>
    <link>http://www.kubat.nl/pages/blogaria/250#250</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <p/>

. . . . . .. . . . . . . . . . . ,.-‘”. . . . . . . . . .``~.,<br/>
. . . . . . . .. . . . . .,.-”. . . . . . . . . . . . . . . . . .“-.,<br/>
. . . . .. . . . . . ..,/. . . . . . . . . . . . . . . . . . . . . . . ”:<br/>,
. . . . . . . .. .,?. . . . . . . . . . . . . . . . . . . . . . . . . . .\,<br/>
. . . . . . . . . /. . . . . . . . . . . . . . . . . . . . . . . . . . . . ,}<br/>
. . . . . . . . ./. . . . . . . . . . . . . . . . . . . . . . . . . . ,:`^}<br/>
. . . . . . . ./. . . . . . . . . . . . . . . . . . . . . . . . . ,:”. . . ./<br/>
. . . . . . .?. . . __. . . . . . . . . . . . . . . . . . . . :`. . . . ./<br/>
. . . . . . . /__.(. . .“~-,_. . . . . . . . . . . . . . ,:`. . . .. ./<br/>
. . . . . . /(_. . ”~,_. . . ..“~,_. . . . . . . . . .,:`. . . . _/<br/>
. . . .. .{.._$;_. . .”=,_. . . .“-,_. . . ,.-~-,}, .~”; /. . .}<br/>
. . .. . .((. . .*~_. . . .”=-._. . .“;,,./`. . /” . . . ./. .. ../<br/>
. . . .. . .\`~,. . ..“~.,. . . . . . . . . ..`. . .}. . . . . . ../<br/>
. . . . . .(. ..`=-,,. . . .`. . . . . . . . . . . ..(. . . ;_,,-”<br/>
. . . . . ../.`~,. . ..`-.. . . . . . . . . . . . . . ..\. . /\<br/>
. . . . . . \`~.*-,. . . . . . . . . . . . . . . . . ..|,./.....\,__<br/>
,,_. . . . . }.>-._\. . . . . . . . . . . . . . . . . .|. . . . . . ..`=~-,<br/>
. .. `=~-,_\_. . . `\,. . . . . . . . . . . . . . . . .\<br/>
. . . . . . . . . .`=~-,,.\,. . . . . . . . . . . . . . . .\<br/>
. . . . . . . . . . . . . . . . `:,, . . . . . . . . . . . . . `\. . . . . . ..__<br/>
. . . . . . . . . . . . . . . . . . .`=-,. . . . . . . . . .,%`>--==``<br/>
. . . . . . . . . . . . . . . . . . . . _\. . . . . ._,-%. . . ..<br/>

<p/>
Ascii art lives! 
</description>
   </item>
   <item>
    <title>Do not drag this image</title>
    <link>http://www.kubat.nl/pages/blogaria/249#249</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/DontDragThisImage.png"
       alt="Do not drag this image"/>
  <p/>
  Cute.
</center>


 
</description>
   </item>
   <item>
    <title>Off The Grid Challenge</title>
    <link>http://www.kubat.nl/pages/blogaria/248#248</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This used to be the blog entry for Off The Grid. I've moved the
information to its separate page <a href="/pages/otg">page</a>.
 
</description>
   </item>
   <item>
    <title>PI like a boss</title>
    <link>http://www.kubat.nl/pages/blogaria/247#247</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seeing the numbers. Like a boss.

<center>
  <img src="/bld/PI-tip.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Once upon a time</title>
    <link>http://www.kubat.nl/pages/blogaria/246#246</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
 <img src="/bld/OnceUponATime.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Dutch eticket system for trains</title>
    <link>http://www.kubat.nl/pages/blogaria/245#245</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/NS-eticket.jpg" class="floatleft"/>

Yesterday I bought an e-ticket for a trip by train. What struck me as
odd, is that when buying the ticket, you have to fill in your name.
Then as you get the PDF with your e-ticket, your name is on the PDF
too. There's a disclaimer stating that the owner of the e-ticket must
identify themselves. Which actually is required; my ID was checked in
the train.

<p/> What bothers me, is that for something as simple as a train trip,
my ID needs to get recorded and checked. This is weird, because when I
buy a ticket with cash, I travel totally anonymously. Sharing my
identity isn't something I am keen on, especially because the Dutch
railroad company (NS) isn't an official governmental body, like the
police, who are entitled to ask for one's ID. What gives?

<p/> So today I looked up the conditions for the use of an e-ticket.
See
<a href="http://www.ns.nl/media/e-ticket/pdf/e-ticket-voorwaarden.pdf"
   target="_blank">http://www.ns.nl/media/e-ticket/pdf/e-ticket-voorwaarden.pdf</a>
for yourself. Apparently;

<ul>

  <li> The ticket is personal and not transferable.</li>
  <li> The ticket is only valid with a legal ID that shows the photo
    of the bearer. </li>
  <li> The ticket is only valid on the date for which it
  intended. </li>

</ul>

There's furthermore a bunch of other conditions, regarding the
printing, paper size etc.. Also, if you look closely, the e-ticket has
a number of security precautions. It looks pretty official! There is
in fact a number of precautions against fraud:

<ul>

  <li> There's a photo on it. Not me, but hey, it's a photo. </li>
  <li> My name is on it, and also it's woven into the photo
    background. </li>
  <li> There's some sort of code on it, looks like a qr code, but it
    isn't. </li>
  <li> Plus there is the aforementioned ticket number.</li>

</ul>

So again, what gives. Is all this necessary just to prevent forgery of
e-tickets? And how effective is this? When train conductors check
e-tickets, they only look at the name, the date, and the provided ID.
That's it. With a PDF editor, tweaking the provided PDF is trivial
(you could change the name, date, whatever). Or any image edting
program can do it. So, in theory, I could buy one e-ticket and travel
for free for the rest of my days. So what is this security worth?
Isn't there another way?

<p/> Of course there is. That's what started me thinking. Here goes, a
high-level design of the NS e-ticket system. Feel free to blow holes
in it ;-)

E-tickets should be anonymous; without needing the bearer's
identification. Also it should be possible to get an e-ticket without
a date restriction - just as a regular ticket. This can be done
easily, here's how.

<p/> First of all, when generating an e-ticket, a <b>ticket number</b>
is generated and put in encrypted form on the PDF, inside a qr code.
At the same time the ticket number is stored centrally, with a
<b>status</b>: <i>unused</i>. Then the PDF is given to the buyer.

<p/> Then, when the train conductor checks the ticket, s/he scans the
qr code, and reads the embedded encrypted ticket number. The scanning
application decrypts the number, and then connects to the central
system that stored the number when generating the e-ticket. 

<ul>

  <li> If the ticket number doesn't occur on the central system, then
    the PDF is a blatant forgery. This situation should not happen at
    all, given the fact that the number on the PDF is encrypted. I'm
    assuming that potential hackers can't get at the encrypted data -
    there is however a precaution, just in case, described below. </li>
  <li> If the central status is <i>unused</i> then all's well, and the
    status is kicked into <i>in use</i>. Or, if the destination is
    almost reached, then the conductor can kick the status
    into <i>used</i>. </li>
  <li> If the status is <i>in use</i> then the conductor assesses that
    the bearer is on a leg of their journey where a previous conductor
    already checked the ticket. If the traveller is nearing their
    destination, then the conductor can change the status
    into <i>used</i>. 
  <li> If the conductor finds that the status is <i>used</i> then
    someone is trying to re-use a previously issued ticket, without
    paying the fare for this trip. (That's of course assuming that
    the same conductor won't check the same e-ticket twice, and bump
    it into the <i>used</i> status.) </li>
  <li> For verification purposes, the conductor can always see who
    changed the previous status, and when. E.g., when a given
    conductor sees that the state of an e-ticket is <i>in use</i>,
    s/he can see when the ticket was last checked, and by which
    colleague. </li>
  <li> Periodically all ticket numbers that have been <i>in use</i>
    for more than 24 hours, are set to <i>used</i>. This is a central
    batch job that regularly checks the states. It's intended to clean
    up old mush. </li>

</ul>

But but.. What if the conductor fails to establish the connection to
the central server? Or what if the connection suddenly dies? This is
what the local app does; it will dutifully do what it's supposed to
do, and will re-sync later once a connection is established. Without a
connection the traveller gets the benefit of the doubt; i.e., when
there's no connection to the central system then the status of an
e-ticket is always assumed to be <i>unused</i>.

<p/> But but.. What if a conductor looses their smartphone, which is found
by a hacker. They could extract the encryption key, and could generate
the encrpyted ticket numbers in qr codes? This in fact won't help
them. The forged ticket number will be either unknown, or it will may
tagged as <i>used</i> in the central system. This is not a valid
attack vector. To top it off, the encryption key can be changed
monthly; so that the duration of this attack would be limited.
Synchronizing a new key with all conductors would of course be the
responsibility of the local app. (In this I'm assuming that the
encryption will be symmetric, e.g., using AES. In the case of
asymmetrical encryption this problem doesn't occur.)

<p/> The ingredients? A smartphone for each conductor, an app for it,
a central database, and a bit of smart coding. The result? Anonymous
e-tickets, not bound to a given date. And an improvement in the
privacy.
 
</description>
   </item>
   <item>
    <title>Is Hell exothermic or endothermic</title>
    <link>http://www.kubat.nl/pages/blogaria/244#244</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I saw this on Akamat's Wordpress blog at <a
					    href="http://akamat.wordpress.com/2009/04/10/bonus-question-is-hell-exothermic-gives-off-heat-or-endothermic-absorbs-heat/">akamat.wordpress.com</a>.
Totally brilliant. We should all be thankful to Teresa for clearing up
this issue.

<p/>

<i>The answer by one student was so 'profound' that the professor
  shared it with colleagues, via the Internet, which is, of course, why
  we now have the pleasure of enjoying it as well:

  <p/>

  <b>Bonus Question: Is Hell exothermic (gives off heat) or endothermic
    (absorbs heat)?</b>

  <p/>

  Most of the students wrote proofs of their beliefs using Boyle's Law
  (gas cools when it expands and heats when it is compressed) or some
  variant.

  <p/>

  One student, however, wrote the following:

  <p/> "First, we need to know how the mass of Hell is changing in time.
  So we need to know the rate at which souls are moving into Hell and
  the rate at which they are leaving, which is unlikely. I think that we
  can safely assume that once a soul gets to Hell, it will not leave.
  There fore, no souls are leaving. As for how many souls are entering
  Hell, let's look at the different religions that exist in the world
  today.

  <p/> Most of these religions state that if you are not a member of
  their religion, you will go to Hell. Since there is more than one of
  these religions and since people do not belong to more than one
  religion, we can project that all souls go to Hell. With birth and
  death rates as they are, we can expect the number of souls in Hell to
  increase exponentially. Now, we look at the rate of change of the
  volume in Hell because Boyle's Law states that in order for the
  temperature and pressure in Hell to stay the same, the volume of Hell
  has to expand proportionately.. as souls are added.

  <p/>

  This gives two possibilities:

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

    <li>If Hell is expanding at a rate faster than the increase of
      souls in Hell, then the temperature and pressure will drop until
      Hell freezes over.</li>
  </ol>

  <p/>
  So which is it?

  <p/> If we accept the postulate given to me by Teresa during my
  Freshman year that, 'It will be a cold day in Hell before I sleep
  with you,' and take into account the fact that I slept with her last
  night, then number two must be true, and thus I am sure that Hell is
  exothermic and has already frozen over. The corollary of this theory
  is that since Hell has frozen over, it follows that it is not
  accepting any more souls and is therefore, extinct... leaving only
  Heaven, thereby proving the existence of a divine being which
  explains why, last night, Teresa kept shouting 'Oh my God.'
  
</i>
 
</description>
   </item>
   <item>
    <title>Optical Illusions</title>
    <link>http://www.kubat.nl/pages/blogaria/243#243</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Recently I saw two geometrical optical illusions on <a
href="http://www.moillusions.com/"
target="_blank">www.moillusions.com</a>. Neat, and not just for the kids.

<p/>
<center>
  <img src="/bld/Illusion1.jpeg"/>
  <p/>
  <img src="/bld/Illusion2.jpeg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Odd lyrics</title>
    <link>http://www.kubat.nl/pages/blogaria/242#242</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Another one off the Cheezburger Network. Pretty funny imho.

<p/>
<center>
  <img src="/bld/BohemianRhapsody/1.png"/>
  <br/>

  <img src="/bld/BohemianRhapsody/2.png"/> 
  <img src="/bld/BohemianRhapsody/3.png"/> 
  <br/>

 <img src="/bld/BohemianRhapsody/4.png"/> 
  <br/>

  <img src="/bld/BohemianRhapsody/5.png"/> 
  <img src="/bld/BohemianRhapsody/6.png"/> 
  <br/>

  <img src="/bld/BohemianRhapsody/7.png"/> 
  <img src="/bld/BohemianRhapsody/8.png"/> 
  <br/>

  <img src="/bld/BohemianRhapsody/9.png"/> 
  <img src="/bld/BohemianRhapsody/10.png"/> 
  <br/>

  <img src="/bld/BohemianRhapsody/11.png"/> 

</center>
 
</description>
   </item>
   <item>
    <title>Band Revival at MON</title>
    <link>http://www.kubat.nl/pages/blogaria/241#241</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/MON/RuudDeVries.png" class="floatright"/> Years ago,
whilst studying in Groningen, I used to play in some bands. The
drummer, Ruud de Vries, whom I hadn't seen in years, followed his
dream and started his own music centre
- <a href="http://www.monoord.nl" target="_blank">Muziek Organisatie
Noord</a>, or MON for short. To celebrate his third year in business
he organized a band revival party; I got to play the base
again and meet all the musicians that I hadn't seen for so long. I
was surprised that the old reflexes came back so fast... I
actually managed to play something.

<p/> The weekend was a blast. Here are three pics.

<p/>
<center>
  <table>
    <tr>
      <td bgcolor="#aaaaaa" width="422" height="820"
	  align="center" valign="center">
	<img src="/bld/MON/mon001.png"/>
	<br/>
	<font size="small" color="gray">Sax rocks.</font>
      </td>
      <td bgcolor="#aaaaaa" width="421" height="820"
	  align="center" valign="center">
	<img src="/bld/MON/mon002.png"/>
	<br/>
	<font size="small" color="gray">Guitar focus.</font>
      </td>
      <td bgcolor="#aaaaaa" width="421" height="820"
	  align="center" valign="center">
	<img src="/bld/MON/mon003.png"/>
	<br/>
	<font size="small" color="gray">Female base players, they exist.</font>
      </td>
  </tr>
  </table>

  <p/>
  (Creative Commons
  License - &copy;Karel Kubat. You may copy &amp; distribute, but must
  attribute by stating my name, e-mail address and copyright stake.)
</center>
 
</description>
   </item>
   <item>
    <title>Protests in the Middle East and you</title>
    <link>http://www.kubat.nl/pages/blogaria/240#240</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen on the Cheeseburger Network, one of the serious subjects. No
words necessary...

<center>
  <img src="/bld/WhatAboutYou.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Mac OSX Hotkey for locking your system</title>
    <link>http://www.kubat.nl/pages/blogaria/239#239</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <b>Finally.</b> I found a way to lock my Mac with just a simple keystroke. Been searching for that for ages now; because I'm not the mousey type and hence, I don't like clicking around.

<ul>

  <li> First of all, make sure that your system requires a password when waking up. I have a delay of 5 seconds after which a password is required (so that when the screensaver kicks in, I can move the mouse and don't have to type the password right away):

    <br/>
    <br/>
    <center>
      <img src="/bld/SecurityTab.png"/>
    </center>
    <br/>
  </li>

  <li> Now you're all set. Anytime you want to lock your system, hit the magic keys <b>Ctrl-Shift-Eject</b>.
  </li>

</ul>
 
</description>
   </item>
   <item>
    <title>dnspb 0.06 is out</title>
    <link>http://www.kubat.nl/pages/blogaria/238#238</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I just uploaded <a href="/pages/dnspb">dnspb version 0.06</a>. Not many changes, just packaging, and there's now a clean build on Linux. I'm using dnspb, and testing-wise, it still works, so I consider it "beta". Have fun with it ;-)
 
</description>
   </item>
   <item>
    <title>Would I buy this fridge</title>
    <link>http://www.kubat.nl/pages/blogaria/237#237</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/SMEG-Fridge.jpg"/>
  <p/>
  Color's ok tho... but it brings back haunting memories of The Young Ones..
</center>
 
</description>
   </item>
   <item>
    <title>InstaYouth</title>
    <link>http://www.kubat.nl/pages/blogaria/236#236</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  Instant youth.. at the power of your fingertips ;-)

  <p/>

  <img src="/bld/InstaYouth.png"/>

  <p/>
  (Ok so with portraits of guys it's not that impressive. Agreed.)
</center>
 
</description>
   </item>
   <item>
    <title>The Thinker is back</title>
    <link>http://www.kubat.nl/pages/blogaria/235#235</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 A few years ago, Rodin's statue The Thinker was stolen - in a flurry of unprecendented criminal ineptitude, which I <a href="/pages/blogaria/76">commented on before</a>. Just a few days ago I saw in the paper that The Thinker's back.. it's a reassuring thought that the Bad Guys didn't leave a permanent mark. Welcome back, Thinker.

<p/>
<center>
  <img src="/bld/ThinkerIsBack.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Math challenge</title>
    <link>http://www.kubat.nl/pages/blogaria/234#234</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 My 15 year old son brought the following assignment to me, and asked
how it's done. Very good question! For the first time with his math
work, I had to think really hard, but alas, in the end: in vain. So
here it is, a little challenge. Be sure to let me know
at <a href="mailto:karel@kubat.nl">karel@kubat.nl</a>. Good solutions
will be rewarded with a honorary mention and of course eternal fame.

<p/>
Given: 

<b>f(x) = -<sup>1</sup>/<sub>6</sub>x<sup>3</sup>
  + <sup>1</sup>/<sub>2</sub>x<sup>2</sup> + 4x + 1</b>


<ul>
  
  <li> Assignment a: <b>f(x)</b> has a tangent at <b>x=2</b>. What is
  the formula for this tangent? </li>

  <li> Assignment b: <b>f(x)</b> has a tangent parallel to the one
  from assignment a. What is the formula for this tangent?

</ul>

The first assignment is pretty easy. You obviously infer the
derivative function of f(x), which is the "a" value ("slope") of the
tangent line y = ax + b. We know x, it's given as 2, so we can compute
y from f(2). So we can compute b.

<p/> But the second assignment really confused me. I stared at it for
half an hour and then gave up. Let me know!

<hr/>
<table>
  <tr>
    <td width="160" valign="top"><img src="/bld/k/happy.jpg"/></td>

    <td>
      <b>Update:</b> And the prize for Eternal Fame goes to... Jos
      Visser. In Dutch: <i>"Kun je niet gewoon de eerste afgeleide
      oplossen voor de coëfficient (a in y=ax+b) van de raaklijn in
      opgave a? De eerste afgeleide is f'(x) = -0.5x^2 + x +4. Die
      afgeleide geeft de coëfficient van de raaklijn op de originele
      curve. Voor x=2 is de coëfficient 4. Nu kun je je f'(x)=4
      oplossen. Dat geeft 2 oplossingen, de ene is 2, de andere is 0.
      Het is al even geleden, maar zo moet het dacht ik."</i>

      <p/> Yep, absolutely right. The derivative function ("slope")
      of f(x) is: <br/>
      <b>f'(x) = -<sup>1</sup>/<sub>2</sub>x<sup>2</sup> + x + 4</b>

      <p/> The slope at x=2 is <b>f'(2)</b> which evaluates to 4. So, the
      parallel tangent will also have the same slope. The question therefore
      is: at which values of x is f'(x) equal to 4? One of the points should
      of course come back as x=2, and the other one is what we need.

      <p/> So, to solve:<br/>

      <b>f'(x) = 4</b>, hence <br/>
      <b>-<sup>1</sup>/<sub>2</sub>x<sup>2</sup> + x + 4 = 4</b>, hence <br/>
      <b>-<sup>1</sup>/<sub>2</sub>x<sup>2</sup> + x = 0</b>

      <p/> Now it only takes the unforgettable a/b/c
      formula <b>x = (-b ± V(b<sup>2</sup> - 4ac)) / 2a</b>, using the
      values a=<sup>1</sup>/<sub>2</sub>, b=1, c=0. This solves to 0
      and 2. Value 2 suggests that this looks right, so x=0 is the
      value we are looking for.

      <p/> The tangent line we're looking for is given by y = ax + b.
      Slope a is 4, x is 0, so b can be computed. Good, I can rest
      peacefully now. It's so simple, once you see the light.

    </td>
  </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Zero tolerance and zero intelligence</title>
    <link>http://www.kubat.nl/pages/blogaria/233#233</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/angry.png" class="floatright"/>

There was an odd newsbit today in the papers, which also appeared on <a href="http://www.webregio.nl/amsterdam-noord/regionaal-nieuws/artikel/1870134/blinde-orgeldraaier-dam-opgepakt.aspx" target="_blank">webregio.nl</a>, one of the Dutch web based newspapers. The original article appeared on <a href="http://www.telegraaf.nl/binnenland/8700658/__Blinde_orgelman_Bennie_opgepakt__.html" target="_blank">telegraaf.nl</a>.

<p/> The jest is, that a blind street musician who never bothered
anyone got picked up by four cops. Reason? He didn't have a permit. He
was detained at the police station for 2 hours, was stripped and
searched, and interrogated. According to Bennie, the street musician,
he was never warned before, and he thinks it's odd that four cops would
pick him up, while they're supposedly so busy crime fighting. The good
man isn't planning to pay the fine, but wants to hear what a judge has
to say about the matter.

<p/> The interesting part in this, was I found, the reaction by the police: "We are here to upkeep the law and this man had no permit. Period." Wait.. What?

<ul>
  
  <li>
    
    The law is not an end by itself. It's a means to safeguard society.
    When the police say they serve and protect.. they surely mean
    <i>society</i>, not the <i>lawbooks</i>, right? At least I should
    hope so!
    
  </li> 

  <li>
    
    This looks to me like a fine case of zero tolerance. And I think, the
    problem with zero tolerance is, that it means zero flexibility. Law
    officers are bound to apply the rules, without any regard to the
    particular situation. The problem with zero flexibility is that it favors
    zero inventivity, zero regard for the social aspects, and in the end,
    zero regard for society's needs. Or for anyone's needs.

 </li>
</ul>

<p/> Zero tolerance breeds zero intelligence.

 
</description>
   </item>
   <item>
    <title>My interest income in 1991</title>
    <link>http://www.kubat.nl/pages/blogaria/232#232</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Whilst cleaning up old stuff, I found out that in the year 1991, I received an interest benefit of - drumroll - 0.27 guilders, yes those were still the days when the Kingdom of the Netherlands counted its cash in guilders and not euro's. My account balance hence increased to a staggering 9.32 guilders. The bank quite correctly informed me that they had to inform the IRS of this fact. I wonder how many civil servants poured over this information.

<p/> I wasn't particularly rich that year, hehehe...

<p/>
<img src="/bld/InterestIncome1991.png"/>

 
</description>
   </item>
   <item>
    <title>Your horoscope by Eddie</title>
    <link>http://www.kubat.nl/pages/blogaria/231#231</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This year good friend Eddie picked up his habit again of providing us a valuable insight in what this year will bring us. A true must read! Don't delay, visit <a href="http://eddie.niese.net/20110101/nieuwjaarshoroscoop_2011/" target="_blank">eddie.niese.net</a> (it's in Dutch).
 
</description>
   </item>
   <item>
    <title>New York City Tours might be half price for you</title>
    <link>http://www.kubat.nl/pages/blogaria/230#230</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/thoughtful.jpg" class="floatright"/>

As Christmas is approaching, here's maybe some cool news for you.
You might be entitled to a 50% discount on CitySights tours in NY!
Maybe you are among the 110.000 people to enjoy a bus tour in the
Great Apple while paying only half of the regular price!

<p/> The reason? On September 26th the CitySights website was
attacked. Using SQL injection, 110.000 credit card records were
stolen, including names, e-mail addresses, credit card numbers, their
expiry dates, and cvv codes. The attack was discovered on October
25th. As a gesture to their customers, CitySights is offering the
discount - to make things right, so to speak.

<p/> So, if you're among those 110.000, be sure to use the 50% discount
coupon code! (Oh and to top it off, the Dept. of
Justice <a href="http://doj.nh.gov/consumer/pdf/twin_america.pdf">published</a>
the coupon code too, so.. even if you're not among the fraud victims, you
can use try the coupon code 012345... Original article is in dutch at at
<a href="http://www.security.nl/artikel/35587/1/Kortingsbon_voor_slachtoffers_creditcarddiefstal.html"
   target="_blank">security.nl</a>.)
 
</description>
   </item>
   <item>
    <title>Weather Forecast</title>
    <link>http://www.kubat.nl/pages/blogaria/229#229</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/WeatherForecast.jpg"/>

<p/>

Today's weather forecast:

<ul>
  <li> Air quality: fairly good </li>
  <li> Hay fever: won't bother me </li>
  <li> I won't get a sunburn </li>
  <li> My rheumatic arthrosis won't bother me at all </li>
  <li> Asthma-wise: not bad, not great </li>
  <li> I'll have some problems sleeping </li>
  <li> I might be bothered by some migraine </li>
</ul>

Isn't science wonderful? <br/>
(Seen in today's morning papers. Where do they get that stuff?)
 
</description>
   </item>
   <item>
    <title>World Economy Collapse explained in 3 minutes</title>
    <link>http://www.kubat.nl/pages/blogaria/228#228</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I was pointed to this video yesterday evening. Pretty hilarious...

<p/>
<center>
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/LyePCRkq620?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/LyePCRkq620?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object>
</center>
 
</description>
   </item>
   <item>
    <title>The Salvation Army and its choice of toys</title>
    <link>http://www.kubat.nl/pages/blogaria/227#227</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I saw this weird newsbit yesterday at <a href="http://cnews.canoe.ca/CNEWS/Canada/2010/12/08/16477981.html" target="_blank">cnews.canoe.ca</a>. The Canadian Salvation Army has an odd choice for childrens' toys:

<p/>
<i>The Salvation Army says it refuses to distribute Harry Potter and Twilight toys collected for needy children because they're incompatible with the charity's Christian beliefs. [The organization] refuses to distribute the Twilight and Harry Potter toys because of their wizardry, vampire and werewolf content, said Capt. Pam Goodyear. "The Salvation Army is based on Christian principles, so these things are not in line with those," said Goodyear.</i>

<p/> <b>However, plastic M16's are ok. They are for the 10-year olds.</b>
<br/>
Is there anything wrong with this picture? No wait let me rephrase. Is there anything right with this picture?
 
</description>
   </item>
   <item>
    <title>Elizabeth thinks highly of me</title>
    <link>http://www.kubat.nl/pages/blogaria/226#226</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Oh the joy! Elizabeth must think very highly of me. She's
just written me a mail, asking for my assistance. Yes! She chose me,
out of the undoubtedly hundreds of people she knows! True, she didn't
inform me about her trip to the UK, bummer. But she did apologize for
it in her mail. It was some kind of business trip thing, so yes, of
course I understand, Elizabeth!

<p/> But then.. disaster struck and she got attacked. All her stuff
got stolen! Oh the horror!! The poor thing! Now she can't even pay for
a coffee. Can you imagine how awful she must feel? Now she doesn't
want to worry her family and friends, they might think that she got
hurt. Oh the dear girl, she's being so considerate to her loved ones!

<p/> She needs a mere 1600 quid to sort it out. And she's asking me
for assistance! In return she'll pay me back, with interest, and I'm
sure I'll earn her eternal gratitude for reaching out in such an
unselfish and helpful manner. Don't despair, Ellie! Help is on its
way, I'm transferring this cash right now! And of course, as you're
asking, I'll send you my phone number right away. I'm eargerly
awaiting your call, wanna meet a bit later on? Why yes, of course I'll
come to Edinburgh to meet you!

<hr/>
<center>
  <img src="/bld/ElizabethWeatherford.png"/>
</center>

 
</description>
   </item>
   <item>
    <title>Should I trust my government with my data</title>
    <link>http://www.kubat.nl/pages/blogaria/225#225</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today in the papers
at <a href="http://www.telegraaf.nl/overgeld/rubriek/belastingen/8415345/__Bende_rooft_via_fiscus__.html"
      target="_blank">De Telegraaf</a> (translation attempt by yours
truly):

<p/>

<i>"<b>AMSTERDAM - Criminal gangs can more and more easily access
  sensitive information at the IRS. Sometimes with cooperation of
  employees of the IRS.</b> <br/>
  It's every tax payer's mightmare: an unknown individual steals your
  fiscal identity and in your name files false statements or cashes
  money. The tax returns disappear into an unknown account, where the
  criminals quickly withdraw the cash. The victim of the data abuse
  usually discovers this too late, the embezzled money is gone. Incase
 false statements have been filed, the victim has a lot of explaining
  to do to the IRS. This fraude is lucrative and fairly simple."</i>

<p/>

So, should I trust my government with my data? No way. They have
bad <a href="/pages/blogaria/112">track</a>
<a href="/pages/blogaria/56">records</a>. Should I trust
<a href="/pages/blogaria/51">large-scale data collections, initiated
by the government</a> (which are of course aimed at the war on
terrorism and child porn) and "guaranteed safe"? Hell no. To make
matters worse, my passport is almost up for renewal, and I'll have to
<a href="/pages/blogaria/161">leave 'em my fingerprint. Shit.</a>
 
</description>
   </item>
   <item>
    <title>Announcing dnspb</title>
    <link>http://www.kubat.nl/pages/blogaria/224#224</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <pre>
     _                 _ 
  __| |_ __  ___ _ __ | |__    This is dnspb, the smart proxy/balancer
 / _` | '_ \/ __| '_ \| '_ \   for DNS over UDP or TCP.
| (_| | | | \__ \ |_) | |_) |
 \__,_|_| |_|___/ .__/|_.__/ 
                |_|
</pre>

<ul>
  <li>Bye bye <a href="/pages/dnsbalancer">dns-balance</a>, my
  prototype of a DNS balancer for UDP. </li>
  <li>Announcing <a href="/pages/dnspb">dnspb</a>, a DNS
  proxy/balancer for UDP and TCP, that knows about back end states,
  supports weights, and much more. </li>
</ul>

Currently alpha-quality - but check it out if you like.
 
</description>
   </item>
   <item>
    <title>Realistic piechart</title>
    <link>http://www.kubat.nl/pages/blogaria/223#223</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/RealisticPiechart.png"/>
  <p/>
  The only realistic pie chart ever. <br/>
  (Via <a href="http://graphjam.memebase.com/"
  target="_blank">http://graphjam.memebase.com/</a>)
</center>
 
</description>
   </item>
   <item>
    <title>Crossroads 2.71 is out</title>
    <link>http://www.kubat.nl/pages/blogaria/222#222</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I've battled a few nasty bugs
in <a href="http://crossroads.e-tunity.com"
target="blank">Crossroads</a> (my pet load balancer). There've been
some nasty 32-bit issues that didn't occur on 64-bit systems. Way down
in the bowels of g++ code generation.

<p/> It took me really a long time to find and fix this, sorry y'all
32-bit users. But finally after 2 days I had it. If you're geeky
enough, here's a short write-up. In Crossroads I'm converting a
pointer (address) to an unsigned value in the range 0..99. The pointer
value is downsized to a bucket number where mutex locks are kept. So,
what I did was something similar to:

<pre>
  unsigned get_bucket_nr(void *ptr) {
    unsigned bucket = (long)ptr % (long)100;
    return bucket;
  }</pre>

This will work like a charm on 64-bit systems, where pointers are long
values. But behold - on 32-bit systems this will sometimes go
abysmally wrong. The return value can be suddenly way outside the
0..99 range. Odd! And of course, as is the case with the really nasty
bugs, this error will not occur all of the time, it won't occur most
of the time, no, it'll occur just ever-so-sparingly to make it
hard to track.

<p/> Well, it's fixed now; I replaced the modulo-operation with a
"real" hash function (based on hashpjw()). If you are a Crossroads
user on a 32-bit system, then please forget about versions 2.69 to
2.70. Get 2.71 or better.

<hr/>
<img src="/bld/GrayCat-small.png" class="floatleft"/>
<font color="red"><b>Update:</b></font> Good buddy Eddie sent me the
following information. I should've known...

<i>"I've just read your blog on Crossroads 2.71 and the overflow bug
  on 32-bit systems.. but, it isn't that odd. Unfortunately you aren't
  using 'unsigned' longs (and in the end, pointers are unsigned). If
  you'd done that, you wouldn't have had the problem.

  <p/> The problem is that you're taking a "negative" number (2's
  complement of a pointer beyond the 2Gb address) and applying
  modulo-100. The C++ specs say that the result is
  implementation-dependent. Your neat x86 processor has different
  'div' instructions (div computes both division and modulo) which
  have different behavior with negative numbers.

  <p/> To be more precise, there are no negative numbers, they may be
  interpreted as negative. There are several instructions for a 2's complement
  operation, div and idiv. With signed operands your compiler uses
  idiv, and with unsigned operands, div. The result that you're seeing
  is that you get a negative number. The result is not "way outside
  the 0..99 range", it's in the range -99..0.

  <p/> You can read it up in the C++ spec, ANSI ISO IEC 14882 §5.6 sub
  4: "The binary / operator yields the quotient, and the binary %
  operator yields the remainder from the division of the first
  expression by the second. If the second operand of / or % is zero
  the behavior is undefined; otherwise (a/b)*b + a % b is equal to a. If
  both operands are nonnegative then the remainder is nonnegative; if
  not, the sign of the remainder is implementation-defined."

  <p/> Your hash function of course solves the problem, but for other
  pointer operations I'd make sure that you are using unsigneds. Even
  intermediate results must be unsigned.. so cast the crap if
  necessary.

  <p/> The fact that this works on 64-bit systems is of course that
  you only run into trouble when you need more than 63 bits for
  addressing. When you approach that value, then it'll also explode.
  It's OS-dependent which virtual address space is used in you
  rprocesses. I think you can tweak a Linux kernel into mapping the
  heap nearby the 64-bit border.. then you would see your code
  toppling too."
</i>

<p/> Thanks Ed, I've taken this to heart. Fortunately I don't have
other pointer arithmetic that involves ints in there, so that's OK.
Also, I'm leaving the hash function in, because it gives less
hash-collisions... Chalk up another one for being precise, and
/faceroll for sloppiness..
 
</description>
   </item>
   <item>
    <title>8 bit Starwars</title>
    <link>http://www.kubat.nl/pages/blogaria/221#221</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I saw this today on <a href="http://celebs.icanhascheezburger.com/"
target="_blank">roflrazzi.com</a> (apparently originally from
<a href="http://www.reddit.com/r/pics/comments/ea2m5/starwars_in_a_gif/"
   target="_blank">reddit.com</a>): the
eight-bit version of Starwars. Brilliant!

<p/>
<center>
  <img src="/bld/8BitStarwars.gif"/>
</center>
 
</description>
   </item>
   <item>
    <title>Six to eight black men</title>
    <link>http://www.kubat.nl/pages/blogaria/220#220</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This was forwarded to me by buddy <a href="http://beerholder.blogspot.com/" target="_blank">Beerholder/BOFH</a>. 't Is the season, so here's a short narrative in 3 parts about some of the weird customs in the Netherlands.
(If the below links no longer work, just go to <a href="http://youtube.com/" target="_blank">youtube</a> and search for "six to eight black men".)

<p/>

<center>
  <object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/sbJpRLhaSqs?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/sbJpRLhaSqs?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object>

  <p/>

  <object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/vU1D1HKTDCY?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/vU1D1HKTDCY?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object>

  <p/>

  <object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/g17Pl7MFMco?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/g17Pl7MFMco?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object>

</center>
 
</description>
   </item>
   <item>
    <title>Canada wants backdoors and data and everything</title>
    <link>http://www.kubat.nl/pages/blogaria/219#219</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/MichaelGeist.gif" class="floatright"/>

A few weeks ago I wrote about the fact that the USA wants <a href="/pages/blogaria/217">backdoors to everything</a>. The oil spill is spreading.

<p/> 
There's an interesting read on Dr. M. Geist's website, at <a href="http://www.michaelgeist.ca/content/view/5451/135/" target="blank">http://www.michaelgeist.ca/content/view/5451/135/</a>. Dr. Michael Geist is a law proffessor with a strong interest in copyright law, net neutrality, privacy and the such - you might've heard of him if you are into these subjects and if you know what the <a href="http://www.eff.org/" target="_blank">EFF</a> does.

</p> Anyway, Michael Geist describes a new proposed bill, which would radically reshape the Canadian Internet:

<ul>

  <li> Internet providers would be mandated to disclose information about their subscribers without intervening court oversight; </li>

  <li> Internet providers would need to implement measures to make it possible to isolate communications from particular subscribers and and intercept these; </li>

  <li> Law enforcement agencies would get new powers to get access to these new possibilities. </li>

</ul>

And here's the kicker: <i>While Internet providers would actively work with law enforcement in collecting and disclosing the subscriber information, they could also be prohibited from disclosing the disclosures as court may bar them from informing subscribers that they have been subject to surveillance or information disclosures.</i> This means that it would be possible to collect data about subscribers and to monitor them, while keeping absolutely silent about it. All fine 'n' legal.

<p/> Let's just hope that this proposal is shot down real fast. It might have a very nasty effect of being predecessor to other countries and/or other measures.

<p/>
<center>
  <i>(Picture comes from <a href="http://www.michaelgeist.ca" target="_blank">http://www.michaelgeist.ca</a>. Above text in italics is quoted.)
  </i>
</center>
 
</description>
   </item>
   <item>
    <title>Autumn storm over the Netherlands</title>
    <link>http://www.kubat.nl/pages/blogaria/218#218</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Oh the joy, autumn's really here. Today's winds reached 100 km/h and
more is expected. Traffic jams have gone through the roof of course.

<p/>
<center>
  <img src="/bld/RainOnMyWindshield-small.jpg"/>
  <p/>
  (<a href="/bld/RainOnMyWindshield.jpg" target="_blank">larger version</a>)
</center>
 
</description>
   </item>
   <item>
    <title>USA wants backdoors to everything</title>
    <link>http://www.kubat.nl/pages/blogaria/217#217</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/eff.gif" class="floatright"/>

There is a very interesting - and scary - article on the <a href="http://www.eff.org/deeplinks/2010/09/government-seeks" target="_blank">Electronic Frontier Foundation's site (EFF)</a>. You should really read it. Apparently, USA's legislators are pushing for backdoors in all encryption-related software, so that their surveillance tasks aren't hindered by the fact that The Bad Guys can engage in private conversation. The Federal goverment's plan is that suppliers of communication software (or of communcation channels/methods) must be able to provide to the FBI a means to listen in on electronic conversations. This was reported by <a href="http://www.nytimes.com/2010/09/27/us/27wiretap.html" target="_blank">the New York Times</a>: <i>"... the Obama administration is drafting a law that would impose a new "mandate" that all communications services be "able to intercept and unscramble encrypted messages" — including ordering "[d]evelopers of software that enables peer-to-peer communication [to] redesign their service to allow interception".</i>

<p/> Let me guess - this is a response to (a) terrorism and (b) child porn, so it must be good? This push is a revival of previous efforts, and of course (and rightly so, I think!) the EFF opposes. 

<p/> But just imagine, what if the legislators got their way. I just can't figure out how that would work.

<ul>

  <li> We have a myriad of programs that engage in point-to-point connections, and that encrypt traffic. <a href="http://www.skype.com" target="_blank">Skype</a> is a great example. You get your list of who's online from the Skype servers, but when you start a conversation, you directly connect with your counterparty. So how would that listening-in functionality get integrated into Skype? I only see one viable option: (a) All traffic would need to be routed over Skype's servers, instead of point-to-point traffic. (b) At the Skype servers, the encryption keys would be known, so that the Feds could tap in when they wanted to do so. Net effect? This blows Skype out of the water. When I talk to my neighbour via Skype and this traffic is routed through the USA, then the product becomes virtually useless. </li>

  <li> The more back doors you build in, the higher the chances that their existence will leak, and that such back doors will be misused by The Bad Guys. Who's going to put measures into place against such misuse? The same Federal government? I don't think so. Their track record isn't that hot. </li>

  <li> How about existing free (or public domain) applications? For example, how about <a href="http://www.openssh.org/" target="_blank">ssh</a>? Is Obama going to stand up and ask, "Say, who's behind this ssh thing. I need you to get up here and rewrite it for us"? Ssh isn't "owned" by one party. There is no-one to address. Are they going to make ssh illegal in the USA? </li>

  <li> Strong encryption is also just such a thing. It's out there, the cat's out, can't put it back again. Cryptographers have given the world methods to secure data transmission so that really no-one can listen in, in all practiality. So now what, are they going to make Rijndael, Blowfish, Twofish and whatnot illegal in the USA? Are they going to make crypto illegal? </li>

  <li> How will they know what programs people are running to communicate? On a TCP stream level, encrypted data looks like rubbish, like random data. How will they know what back door to open? They'd need to identify one stream of random data as a Skype conversation, or another stream as a https connection, and so on. How do they think they'll be able to do that? </li>

  <li> Then there's the issue with national borders. Obviously the sane remainder of the world will switch to a non-crippled Skype-lookalike. But then, when I'm in the USA, and I want to talk to my neighbour, will using my Skype-lookalike be outlawed? Do they have the right to do that? </li>

  <li> This is going to turn into another cat-and-mouse game. That's pretty obvious. End result - the Bad Guys will of course use new technologies to protect their privacy, the Federal government will be chasing such products to get back doors in, the rest of us will be hindered by all the hassle, and all this is going to eat up vast amounts of money. </li>

  <li> Last but not least - this is a huge breach of personal privacy. It's a great way of paving the road for a police state. </li>

</ul>

The whole plan is not well thought of, dangerous, and just plain stupid. Putting dangerous tools into the hands of stupid people never helped anyone. The plan is just bad. 
 
</description>
   </item>
   <item>
    <title>Sudoku solver in Perl</title>
    <link>http://www.kubat.nl/pages/blogaria/216#216</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 While cleaning up an old backup disk, I came across this Sudoku
solver. It would be shame to just delete it.. so I might just as well
park it here. I still remember its origins: Some years ago I was working
with a couple of co-geeks at a bank. Each month we'd take a look at
the corporate newsletter, which had a Sudoku puzzle on the last page.
Solving the puzzle and sending in the solution could win you a small
prize, a free lunch or something.

<p/> No better challenge than this, of course. I wrote the solver,
used it for fun to solve the monthly puzzle, and I kept e-mailing back
the solutions. I'd make it a sport to send back the solution within
seconds of receiving the newsletter. Actually, I never won that free
lunch, I think they figured out that I wasn't cracking numbers in my
mind.

<p/> Here's the principle. You get a 9x9 matrix where each cell is
allowed to hold one digit, 1 through 9. On each row of the matrix and
on each column the digits 1 through 9 must occur just once. For
example, below is a puzzle. The question is how to fill in the blanks:

 <table>
   <tr>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">7</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">3</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">8</td>
   </tr>
   <tr>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">2</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">1</td>
     <td style="background: lightgray">4</td>
   </tr>
   <tr>
     <td style="background: lightgray">1</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">8</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">4</td>
     <td style="background: lightgray">7</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
   </tr>
   <tr>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">8</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">5</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
   </tr>
   <tr>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">7</td>
     <td style="background: lightgray">8</td>
     <td style="background: lightgray">1</td>
     <td style="background: lightgray">2</td>
     <td style="background: lightgray">9</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
   </tr>
   <tr>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">4</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">8</td>
     <td style="background: lightgray"></td>
   </tr>
   <tr>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">5</td>
     <td style="background: lightgray">6</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">3</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">9</td>
   </tr>
   <tr>
     <td style="background: lightgray">7</td>
     <td style="background: lightgray">2</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">6</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
   </tr>
   <tr>
     <td style="background: lightgray">6</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">4</td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray"></td>
     <td style="background: lightgray">7</td>
     <td style="background: lightgray"></td>
   </tr>
 </table>

<p/>
<hr/>
 And here's how to operate the solver.

 <ul>

   <li>First, write down the puzzle in
     the following format: per line, put in a hyphen for a blank spot, or a
     digit for a digit. The above puzzle is therefore:

     <pre>
-7--3---8
--2----14
1-8--47--
-8---5---
--78129--
---4---8-
--56--3-9
72----6--
6---4--7-</pre></li>

   <li>Save this in a file, e.g. <i>/tmp/puzzle</i></li>

   <li>Now run: <i>sudoku silent &lt; /tmp/puzzle</i> Or if you want a
   lot of output, run <i>sudoku trace &lt; /tmp/puzzle</i> </li>

 </ul>

 <hr/>
 Enough explanation. Here's the solver, have fun with it.

 <pre>
#!/usr/bin/perl

use strict;
my @table;
my $verbose = 0;

if ($#ARGV != 0 or ($ARGV[0] ne 'trace' and $ARGV[0] ne 'silent')) {
    die <<"ENDUSAGE";

Usage: sudoku trace
   or: sudoku silent

Expects input table on stdin, where each line contains hyphens or
numbers. E.g. the following is a valid table. There are 9 characters
in each row, and 9 rows:  

-7--3---8
--2----14
1-8--47--
-8---5---
--78129--
---4---8-
--56--3-9
72----6--
6---4--7-

You can also use dots instead of hyphens to indicate empty spaces.
The solution (if any) is shown.

Argument 'trace' shows what's going on. Argument 'silent' produces
way less output.
  
ENDUSAGE
}
$verbose++ if ($ARGV[0] eq 'trace');

# Read table.
for my $y (0..8) {
    my $line = <STDIN>;
    chomp ($line);
    my @chars = split ('', $line);
    for my $x (0..8) {
	settable ($x, $y, $chars[$x]);
    }
}
showtable("Starting with table:\n", 0, 0);
print ("Working..\n");

if (solve (0, 0)) {    
    showtable("Solved:\n", 0, 0);
} else {
    print ("No solution found.\n");
}

#########################################################################

sub solve ($$) {
    my ($x, $y) = @_;

    return (1) if ($x < 0 or $x > 8 or $y < 0 or $y > 8);
    
    if (gettable ($x, $y)) {
	msg ($x, $y, "Table at already occupied by ", gettable($x, $y),
	     ", trying next\n");
	my $ret = solve (nextcoord ($x, $y));
	return ($ret);
    }

    for my $n (1..9) {
	if (tablefree ($x, $y, $n)) {
	    msg ($x, $y, "Trying $n\n");
	    settable ($x, $y, $n);
	    msgtable ("Trying:\n", $x, $y);
	    if ( ($x == 8 and $y == 8) or (solve (nextcoord ($x, $y))) ) {
		msg ($x, $y, "Leaving $n\n");
		return (1);
	    }
	    settable ($x, $y, 0);
	}
    }
    msg ($x, $y, "Resetting\n");
    settable ($x, $y, 0);
    return (undef);
}

sub msg {
    my $x = shift;
    my $y = shift;

    return unless ($verbose);

    for my $i (0..( $x + 8 * $y)) {
	print (' ');
    }
    print ("[$x,$y]: ", @_);
}

sub nextcoord ($$) {
    my ($x, $y) = @_;
    if ($x < 8) {
	return ($x + 1, $y);
    } else {
	return (0, $y + 1);
    }
}

sub tablefree ($$$) {
    my ($x, $y, $n) = @_;

    for my $i (0..8) {
	if ($i != $y and gettable ($x, $i) == $n) {
	    msg ($x, $y, "$n not possible, already on y=$i\n");
	    return (undef)
	}
	if ($i != $x and gettable ($i, $y) == $n) {
	    msg ($x, $y, "$n not possible, already on x=$i\n");
	    return (undef);
	}
    }

    my ($startx, $starty, $endx, $endy);
    if ($x > 5) {
	$startx = 6; $endx = 8;
    } elsif ($x > 2) {
	$startx = 3; $endx = 5;
    } else {
	$startx = 0; $endx = 2;
    }
    if ($y > 5) {
	$starty = 6; $endy = 8;
    } elsif ($y > 2) {
	$starty = 3; $endy = 5;
    } else {
	$starty = 0; $endy = 2;
    }
    for my $xx ($startx..$endx) {
	for my $yy ($starty..$endy) {
	    if ($x != $xx and $y != $yy and gettable ($xx, $yy) == $n)  {
		msg ($x, $y, "$n not possible, already on x=$xx, y=$yy\n");
		return (undef);
	    }
	}
    }

    msg ($x, $y, "$n is allowed here\n");
    return (1);
}

sub settable ($$$) {
    my ($x, $y, $ch) = @_;
    die ("Bad table input '$ch'\n")
      if ($ch ne '-' and $ch ne '.' and
	  ($ch lt '0' or $ch gt '9'));
    return if ($ch eq '-' or $ch eq '.');

    $table[$y] = [ 0,0,0, 0,0,0, 0,0,0, 0,0,0 ]
      unless (defined ($table[$y]));

    my @row = @{ $table[$y] };
    $row[$x] = $ch;
    $table[$y] = \@row;
}

sub msgtable ($$$) {
    return unless ($verbose);
    showtable (@_);
}

sub showtable ($$$) {
    my ($title, $xx, $yy) = @_;
    
    for my $i (0..( $xx + 8 * $yy)) {
	print (' ');
    }
    print ($title);
    for my $y (0..8) {
	for my $i (0..( $xx + 8 * $yy)) {
	    print (' ');
	}
	print ("    |");
	for my $x (0..8) {
	    my $ch = gettable ($x, $y);
	    if ($ch > 0) {
		print ($ch);
	    } else {
		print (' ');
	    }
	    print ('|');
	}
	print ("\n");
    }
    print ("\n");
}

sub gettable ($$) {
    my ($x, $y) = @_;
    return (0) unless (defined ($table[$y]));
    my @row = @{ $table[$y] };
    return ($row[$x]);
}</pre>
 
</description>
   </item>
   <item>
    <title>Finally wrote up a Syscheck page</title>
    <link>http://www.kubat.nl/pages/blogaria/215#215</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/phat.jpg" class="floatright"/>

I finally wrote up a page on <a href="/pages/syscheck">syscheck</a>, a neat little homegrown tool that I use for self-monitoring and self-healing of Unix boxes. Hope you like it too. The documentation shows what it does, how the configuration file is structured, lists some examples, and so on. 
 
</description>
   </item>
   <item>
    <title>Neon sign fail</title>
    <link>http://www.kubat.nl/pages/blogaria/214#214</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 [Dutch entry.. this is too language-specific.]

<p/> Gisteravond, op bezoek bij mijn schoonbroer in Vianen:

<center>
  <img src="/bld/OuweMode.jpg"/>
</center>

<p/> Als je goed kijkt had er Brouwers moeten staan ;-) Toch bijzonder als neonletters zo specifiek uitvallen!
 
</description>
   </item>
   <item>
    <title>The Renault Eco Team</title>
    <link>http://www.kubat.nl/pages/blogaria/213#213</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This got me a chuckle. Some time ago I saw a Renault Eco Team car. Except they were driving a Dacia Duster... Maybe they couldn't get a good deal at the Renault shop?
<br/> <p/> 

<center>
  <img src="/bld/RenaultEco1.jpg"/>
  <br/> <p/> <br/> 
 <img src="/bld/RenaultEco2.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Crossroads 2.68 is out</title>
    <link>http://www.kubat.nl/pages/blogaria/212#212</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/GrayCat-small.png" class="floatleft"/>

I just put out version 2.68 of my pet loadbalancer Crossroads; check out the primary site <a href="http://crossroads.e-tunity.com" target="_blank">crossroads.e-tunity.com</a>, or sign up at the forum <a href="http://xrforum.org" target="_blank">xrforum.org</a>. This version has some important fixes in HTTP header rewrites, in mutex handling, and in verbose/debug messaging. Worth a spin. 

<p/> Regarding mutex handling, I think I got a neat speedup. For the techies: Mutexes are contained in nodes that can be locked or unlocked. The nodes are kept in binary trees for faster access. Finally, for even faster access, I have a hashtable of 50 trees so that unbalanced or overfull trees are avoided. Basically I described this <a href="/blogaria/168#168">previously</a>, except that in the Crossroads version of this code, I added the hash table. 

I also extended the mutex nodes with a method <i>trylock()</i>, which obviously gets a lock, or fails - but doesn't block. I'm using this in the messaging which generates the tons of debug info: when debugging is on, then instead of blocking Crossroads due to a mutex lock, I rather drop a debug line. Works quite well.
 
</description>
   </item>
   <item>
    <title>How to suppress Flash cookies</title>
    <link>http://www.kubat.nl/pages/blogaria/211#211</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/sillywalk-small.jpg" class="floatright"/>

<p/> It's quite public knowledge that Adobe's Local Shared Objects
(LSO's) are used to track browsing habits - they're more often called
Flash Cookies (since Flash is usually the one who creates them). This
means, that even if you instruct your browser to clear regular cookies
at startup (or if you treat persistent cookies as transient), you can
be still pretty sure that your browsing behavior is being tracked.
Flash cookies are "the next thing" to track your browsing habits,
since regular third-party cookies are nowadays so often blocked by
browsers, or automatically deleted.

<p/>Flash cookies work just like ordinary third-party cookies. When
you visit a site, there's a good chance that you will be confronted
with a Flash ad. Such an ad is typically not served from the site
itself, but from a third-party ad server. This Flash-based ad will now
happily leave a Flash cookie on your system. When you visit another
site that also serves a Flash ad that's pulled in from the same ad
server, then the connection is made, and there you already have a
browsing history spanning two sites. And so on. Current estimates are
that about 50% of all sites leave Flash cookies on your system, which
is a pretty valuable resource for measuring your browsing habits.

<p/> The problem with suppressing flash cookies is that they are
outside of the browser's control. A different piece of software
(Flash) creates and reads such cookies; without knowledge or consent
of the browser. Typical browser addons therefore won't be able to help
out; the standard privacy controls are useless here. Adobe does offer
some settings - you can "opt out" of LSO generation on a per-domain
basis, or even globally. However even after opting out, Flash cookies
seem to be reappearing.

<p/> So as a suggestion, here's a more radical way of dealing with
Flash cookies: simply <b>forbid them on a operating system level</b>.
OS-level? Yes! That's why we have an operating system - to force
ill-behaving software into submission ;-) Here is where LSO's are
stored under Mac OSX:

<ul>

  <li> <i>~/Library/Preferences/Macromedia/Flash
  Player/#SharedObjects/</i> </li>

  <li> <i>~/Library/Preferences/Macromedia/Flash
  Player/macromedia.com/support/flashplayer/sys/</i> </li>

</ul>

Adobe LSO's will occur under these directories (maybe under
subdirectories under them). So what's easier than to (a) empty out
those directories, (b) to make then non-readable?

<p/> I've tried this out and it works like a charm. The Flash-based
sites that I visit still work just fine, but Flash cookies are
gone. The only drawback is that one day Adobe might decide to make a
cookie-directory writable, when it sees that the file permissions are
too strict. But hey, that'll be another day. So far so good!

<p/> For your enjoyment: below is a script that does just this, for
Mac OSX. A very similar script could be devised for Linux, or even
maybe something for Windows. If you want to know where Flash cookies
are stored on Windows or Linux, read
<a href="http://en.wikipedia.org/wiki/Local_Shared_Object"
   target="_blank">http://en.wikipedia.org/wiki/Local_Shared_Object</a>.

<p/> Right, so here's the little script. Tested and found working - at
least, for me - but use it at your own risk. 

<pre>
#!/bin/sh

case $(uname) in
    Darwin)
	echo 'About to suppress Flash cookies for this user.'
	;;
    *)
	echo 'Sorry, this OS is not supported by this script.'
	exit 1
	;;
esac

cd "$HOME/Library/Preferences/Macromedia/Flash Player" || exit 1
rm -rf '#SharedObjects' || exit 1
mkdir '#SharedObjects' || exit 1
chmod a-w '#SharedObjects' || exit 1
echo "$(pwd)/#SharedObjects dir cleaned and made non-writable."

cd "$HOME/Library/Preferences/Macromedia/Flash Player/macromedia.com/support/flashplayer" || exit 1
rm -rf 'sys' || exit 1
mkdir 'sys' || exit 1
chmod a-w 'sys' || exit 1
echo "$(pwd)/sys dir cleaned and made non-writable."

echo '** All done! **'
</pre>
 
</description>
   </item>
   <item>
    <title>Meanwhile on Facebook</title>
    <link>http://www.kubat.nl/pages/blogaria/210#210</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/Funny Facebook Fails - It's Science!.jpeg"/>

  <p/>
  Lol! I particlarly like the "Copernicus likes this" touch.<br/>
  (Seen on <a href="http://failbook.failblog.org"
  target="_blank">failbook.failblog.org</a>) 
</center>
 
</description>
   </item>
   <item>
    <title>The Yes Men Fix The World</title>
    <link>http://www.kubat.nl/pages/blogaria/209#209</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/TheYesMen.png"/>
</center>

<p/>

just yesterday I watched "The Yes Men Fix the World" - a real must-see if you're into that kind of thing. This is the story of two guys who pretend to be spokesmen of corporations, or the government, or whatever - but, what they say is what they think that <i>should've been said or done in the first place, instead of chasing profit, or voters</i>. Eventually of course the truth comes out, that they are not speaking on behalf of the organizations they're pretending to represent. By then it's called a hoax - but the movie nicely shows how idealistic such a hoax can be. And what effects it can have.

<p/> This movie has been gagged from appearing in certain settings, and these guys themselves have made it available via bittorrent. So, just go to <a href="http://www.isohunt.com" target="_blank">isohunt.com</a>, or <a href="http://www.thepiratebay.org" target="_blank">thepiratebay.org</a>, or any other bittorrent tracker, and download it. It's great for two hours of semi-serious fun.

<p/>
<img src="/bld/warning.png" class="floatleft"/>
Update: I should also mention The Yes Men's site - which is <a href="http://http://theyesmen.org/" target="_blank">http://theyesmen.org</a>. Very much worth a visit.
 
 
</description>
   </item>
   <item>
    <title>ed is not dead</title>
    <link>http://www.kubat.nl/pages/blogaria/208#208</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Some dinosaurs just refuse to go extinct. From a very long time ago I still remember <i>ed</i>, the "standard" Unix line-oriented editor. It eventuall evolved into <i>vi</i>, a fullscreen visual variant. Good ol' <i>vi</i> still bears the the scars of its heritage - such as a separate command mode and a separate insert mode. For me, the good days only started with <i>emacs</i>, the first beast that really made sense - and was totally programmable, something that every editor should have. And still, the old dino won't roll over and die. Seen today on <a href="http://freshmeat.net" target="blank">freshmeat</a>:

<p/>
<center>
  <img src="/bld/GNU-ed.png"/>
</center>
<p/>

I know I'm going to have nightmares tonight.
 
</description>
   </item>
   <item>
    <title>Installing Perl modules in a non root environment</title>
    <link>http://www.kubat.nl/pages/blogaria/207#207</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/scratch.png" class="floatright"/>

Yesterday I had to install a few Perl modules as non-root. It took me
a while to <del>Google this</del> figure this out, so here's a synopsis.

<p/> When starting <i>cpan</i> for the first time, you're presented
with a number of options - such as, where are the nearest mirrors.
There's also an option to specify the <i>PREFIX</i> under which all
stuff is supposedly installed. One would think that that's enough, but
alas: apparently, older Perl modules don't obey the <i>PREFIX</i> and
require additional work. Here's how.


<h3> Step 1: Choose a location</h3>

First of all, decide where the non-root-owned Perl modules will go.
For example, this might be <i>~/localperl</i>. In that case, create
the directories, including subdirs <i>man1</i> and <i>man3</i>:

<pre>mkdir -p ~/localperl/man1 ~/localperl/man3</pre>
    
<h3> Step 2: Patch up the CPAN configuration</h3>

Next, start <i>cpan</i> and define a few build parameters. In the cpan
shell, enter:

<pre>o conf makepl_arg "LIB=~/localperl PREFIX=~/localperl INSTALLSITEMAN1DIR=~/localperl/man/man1 INSTALLSITEMAN3DIR=~/localperl/man/man3"
o conf make_install_arg UNINST=0
o conf commit</pre>

After this, you can exit <i>cpan</i>.

<h3> Step 3: Install any modules you need</h3>

Next, install anything you want. E.g., inside the <i>cpan</i> shell,
type <i>install XML::Simple</i>. This module (and all dependencies)
will appear under <i>~/localperl</i>.

<h3>Step 4: How to use the modules</h3>

Adding the diretory <i>~/localperl</i> to the Perl search path is
standard:

<ul>

  <li>
    Add <i>~/localperl</i> to the environment variable LIB. E.g.,
    in your profile, add:

    <pre>export LIB=$LIB:~/localperl</pre>

  </li>

  <li>
    Alternatively, fix up Perl scripts to look in <i>~/localperl</i>
    as follows:

    <pre>BEGIN { push(@INC, '/home/username/localperl'); }
use XML::Simple;</pre>
  </li>

</ul>
 
</description>
   </item>
   <item>
    <title>Magic self leviation</title>
    <link>http://www.kubat.nl/pages/blogaria/206#206</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This was shown to me today.

<p/>

<object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/UcGTiz5Djng?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/UcGTiz5Djng?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object>

<p/>
<b>Gravity is not just a good idea. It's the law.</b> 
</description>
   </item>
   <item>
    <title>Google Chrome does not support offline Gmail</title>
    <link>http://www.kubat.nl/pages/blogaria/205#205</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Attempts to support your own software can go haywire and apparently have their own sense of irony. The way I access my Gmail account doesn't support offline mail - because I use Google Chrome to access it...

<p/>
<img src="/bld/Chrome-Offline-Gmail.png"/>
<p/>

<p/>
Hmmm... Ok, but why? Offline storage uses Google Gears.. So do I have that installed at all?

<img src="/bld/Google-Gears.png"/>

Yeah, unsupported. That's <b>so</b> me.
 
</description>
   </item>
   <item>
    <title>The number 48</title>
    <link>http://www.kubat.nl/pages/blogaria/204#204</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Well, it's August 19th again. Happens every year, but as a
compensation I get presents! On the upside, in a base24 numeric system
I'm only 20 years old. On the downside, octally speaking I'm 60.
Here's how you write 48 in different numeric bases. There's a little
generator too if you're interested.

<table>
<tr>
<td valign="top">  
<table>
<tr><th><b>Base</b></th><th>Representation</th></tr>
<tr><td align="right" style="background: #e0e0e0">2</td><td align="right" style="background: #e0e0e0">110000</td></tr>
<tr><td align="right" style="background: #e0e0e0">3</td><td align="right" style="background: #e0e0e0">1210</td></tr>
<tr><td align="right" style="background: #e0e0e0">4</td><td align="right" style="background: #e0e0e0">300</td></tr>
<tr><td align="right" style="background: #e0e0e0">5</td><td align="right" style="background: #e0e0e0">143</td></tr>
<tr><td align="right" style="background: #e0e0e0">6</td><td align="right" style="background: #e0e0e0">120</td></tr>
<tr><td align="right" style="background: #e0e0e0">7</td><td align="right" style="background: #e0e0e0">66</td></tr>
<tr><td align="right" style="background: #e0e0e0">8</td><td align="right" style="background: #e0e0e0">60</td></tr>
<tr><td align="right" style="background: #e0e0e0">9</td><td align="right" style="background: #e0e0e0">53</td></tr>
<tr><td align="right" style="background: #e0e0e0">10</td><td align="right" style="background: #e0e0e0">48</td></tr>
<tr><td align="right" style="background: #e0e0e0">11</td><td align="right" style="background: #e0e0e0">44</td></tr>
<tr><td align="right" style="background: #e0e0e0">12</td><td align="right" style="background: #e0e0e0">40</td></tr>
<tr><td align="right" style="background: #e0e0e0">13</td><td align="right" style="background: #e0e0e0">39</td></tr>
<tr><td align="right" style="background: #e0e0e0">14</td><td align="right" style="background: #e0e0e0">36</td></tr>
<tr><td align="right" style="background: #e0e0e0">15</td><td align="right" style="background: #e0e0e0">33</td></tr>
<tr><td align="right" style="background: #e0e0e0">16</td><td align="right" style="background: #e0e0e0">30</td></tr>
<tr><td align="right" style="background: #e0e0e0">17</td><td align="right" style="background: #e0e0e0">2e</td></tr>
<tr><td align="right" style="background: #e0e0e0">18</td><td align="right" style="background: #e0e0e0">2c</td></tr>
<tr><td align="right" style="background: #e0e0e0">19</td><td align="right" style="background: #e0e0e0">2a</td></tr>
<tr><td align="right" style="background: #e0e0e0">20</td><td align="right" style="background: #e0e0e0">28</td></tr>
<tr><td align="right" style="background: #e0e0e0">21</td><td align="right" style="background: #e0e0e0">26</td></tr>
<tr><td align="right" style="background: #e0e0e0">22</td><td align="right" style="background: #e0e0e0">24</td></tr>
<tr><td align="right" style="background: #e0e0e0">23</td><td align="right" style="background: #e0e0e0">22</td></tr>
<tr><td align="right" style="background: #e0e0e0">24</td><td align="right" style="background: #e0e0e0">20</td></tr>
<tr><td align="right" style="background: #e0e0e0">25</td><td align="right" style="background: #e0e0e0">1n</td></tr>
<tr><td align="right" style="background: #e0e0e0">26</td><td align="right" style="background: #e0e0e0">1m</td></tr>
<tr><td align="right" style="background: #e0e0e0">27</td><td align="right" style="background: #e0e0e0">1l</td></tr>
<tr><td align="right" style="background: #e0e0e0">28</td><td align="right" style="background: #e0e0e0">1k</td></tr>
<tr><td align="right" style="background: #e0e0e0">29</td><td align="right" style="background: #e0e0e0">1j</td></tr>
<tr><td align="right" style="background: #e0e0e0">30</td><td align="right" style="background: #e0e0e0">1i</td></tr>
<tr><td align="right" style="background: #e0e0e0">31</td><td align="right" style="background: #e0e0e0">1h</td></tr>
<tr><td align="right" style="background: #e0e0e0">32</td><td align="right" style="background: #e0e0e0">1g</td></tr>
<tr><td align="right" style="background: #e0e0e0">33</td><td align="right" style="background: #e0e0e0">1f</td></tr>
<tr><td align="right" style="background: #e0e0e0">34</td><td align="right" style="background: #e0e0e0">1e</td></tr>
<tr><td align="right" style="background: #e0e0e0">35</td><td align="right" style="background: #e0e0e0">1d</td></tr>
<tr><td align="right" style="background: #e0e0e0">36</td><td align="right" style="background: #e0e0e0">1c</td></tr>
<tr><td align="right" style="background: #e0e0e0">37</td><td align="right" style="background: #e0e0e0">1b</td></tr>
<tr><td align="right" style="background: #e0e0e0">38</td><td align="right" style="background: #e0e0e0">1a</td></tr>
<tr><td align="right" style="background: #e0e0e0">39</td><td align="right" style="background: #e0e0e0">19</td></tr>
<tr><td align="right" style="background: #e0e0e0">40</td><td align="right" style="background: #e0e0e0">18</td></tr>
<tr><td align="right" style="background: #e0e0e0">41</td><td align="right" style="background: #e0e0e0">17</td></tr>
<tr><td align="right" style="background: #e0e0e0">42</td><td align="right" style="background: #e0e0e0">16</td></tr>
<tr><td align="right" style="background: #e0e0e0">43</td><td align="right" style="background: #e0e0e0">15</td></tr>
<tr><td align="right" style="background: #e0e0e0">44</td><td align="right" style="background: #e0e0e0">14</td></tr>
<tr><td align="right" style="background: #e0e0e0">45</td><td align="right" style="background: #e0e0e0">13</td></tr>
<tr><td align="right" style="background: #e0e0e0">46</td><td align="right" style="background: #e0e0e0">12</td></tr>
<tr><td align="right" style="background: #e0e0e0">47</td><td align="right" style="background: #e0e0e0">11</td></tr>
<tr><td align="right" style="background: #e0e0e0">48</td><td align="right" style="background: #e0e0e0">10</td></tr>
</table>
</td>

<td valign="top">
<pre>use strict;

# Shamelessly ripped from http://www.perlmonks.org/?node_id=27148
# Orignal code by ikegami

my @nums = (0..9,'a'..'z','A'..'Z');
my %nums = map { $nums[$_] =&gt; $_ } 0..$#nums;

sub to_base ($$) {
    my $base   = shift;
    my $number = shift;
    return $nums[0] if $number == 0;
    my $rep = "";
    while ($number &gt; 0) {
	$rep = $nums[$number % $base] . $rep;
	$number = int($number / $base);
    }
    return $rep;
}

for my $base (2..48) {
    print("Base: $base -- ", to_base($base, 48), "\n");
}</pre>
</td>
</tr>
</table>
 
</description>
   </item>
   <item>
    <title>Welsh trout mini HOWTO</title>
    <link>http://www.kubat.nl/pages/blogaria/203#203</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 During our week off in Wales we had a great time one afternoon getting
some rainbow trout for dinner. Here's some pics.

<h2>Step 1: Get the fish</h2>

<table style="font-size: 8pt">
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/Lake01.jpg"/>
      <br/>
      Find a lake.
    </td>
  </tr>
</table>

<table>
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/GotOne01.jpg"/>
      <br/>
      Start fishing.
    </td>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/KidsFun02.jpg"/>
      <br/>
      Got one!
    </td>
  </tr>
</table>

<table style="font-size: 8pt">
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/FishInNet.jpg"/>
      <br/>
      One more!
    </td>
  </tr>
</table>

<h2>Step 2: Preparation</h2>

<table>
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/CleanFish01.jpg"/>
      <br/>
      Six trouts all cleaned out
    </td>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/CleanFish02.jpg"/>
      <br/>
      Looking just fine.
    </td>
  </tr>
</table>

<h2>Step 3: Cooking</h2>

<table style="font-size: 8pt">
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/Barbecue01.jpg"/>
      <br/>
      Barbecue time
    </td>
  </tr>
</table>
<table style="font-size: 8pt">
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/Barbecue02.jpg"/>
      <br/>
      Lovely pink meat
    </td>
  </tr>
</table>

<h2>Step 4: Dinner time!</h2>

<table style="font-size: 8pt">
  <tr>
    <td style="background: #e0e0e0; padding: 10px">
      <img src="/bld/WelshTrout/Dinner.jpg"/>
      <br/>
      Dinner time
    </td>
  </tr>
</table>

<h2>Step 5: Cleanup</h2>

No photos there. I just did <br/>
<b>su kids -c "make clean || receive punishment"</b> <br/>
Worked like a charm.
 
</description>
   </item>
   <item>
    <title>Fooling a NetCache proxy into fetching forbidden files</title>
    <link>http://www.kubat.nl/pages/blogaria/202#202</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/happy.jpg" class="floatright"/>Yesterday I had an interesting hacking session regarding proxies and
the such. We were trying to get Maven (a Java build tool) to get to
work in a corporate environment where the outgoing proxy is a NetCache
appliance - in our case NetApp/5.6.2R1. When we fired up Maven, and
the process tried to fetch extra modules from the Internet. And
failed. Oh of course! We'd forgotten to tell Maven to talk to the
Internet via an outgoing proxy...

<p/> <b>Ok, step 1</b>. We configured Maven to use an external proxy
for Internet contact, with the right proxy credentials. Then we
retried. Still no luck. The outgoing proxy would block <i>.jar</i>
files with a "403 forbidden" error. I've seen this behavior before,
outgoing proxies will try to protect unsuspecting users from fetching
e.g. <i>.exe</i> files - which will typically be a Trojan trying to infect the corporate network environment. But I'd never seen the blocking of jars yet. We could reproduce this fairly easily with a <i>wget</i>, as follows:

<pre>prompt: export http_proxy=http://proxyuser:proxypass@proxyhost:8080
prompt: wget -SO- http://where.ever.org/some/place/somefile.jar
Proxy request sent, awaiting response... 
  HTTP/1.0 403 Forbidden
  Date: Wed, 03 Aug 2010 10:23:02 GMT
  Content-Length: 257
  Content-Type: text/html
  Server: NetCache appliance (NetApp/5.6.2R1)
2010-08-04 12:23:00 ERROR 403: Forbidden.
prompt:</pre>  

Ah well.

<p/> Now in a browser or at the command line, that's pretty trivial to circumvent. The NetCache can be easily fooled by specifying the final dot in the filename as "%2e", which is the hexadecimal notation for the dot. So, the following command would succeed:

<pre>prompt: wget 'http://where.ever.org/some/place/somefile%2ejar'</pre>

But but but.. you can't get an existing system like Maven to recode dots into %2e. Now what?

<p/> <b>Right, on to step 2</b>. More hacking and drilling holes. Perl's
HTTP::Proxy to the rescue! I wrote up a small intermediate Perl proxy
to recode dots into %2e, and forward the request onto the outgoing
NetCache proxy. Without ado - here's the code. In order to make this
work, you'll probably first need to install HTTP::Proxy using Perl's cpan.

<pre>#!/usr/bin/env perl

use strict;
use HTTP::Proxy qw(:log);
use HTTP::Proxy::HeaderFilter;

# Configuration section. Edit only this part.
# -------------------------------------------
my $configuration =  
  {
   # The downstream proxy
   proxyserver => 'the-proxy-hostname',
   proxyport   => 8080,
   proxyuser   => 'the-proxy-username',
   proxypass   => 'the-proxy-password',

   # Hosts to exclude from going to the external proxy
   noproxy     => '127.0.0.1, 10.1.1.1, 10.1.1.2', 

   # Log level of this proxy. Set to NONE to get errors only.
   loglevel    => NONE,
   # loglevel  => PROXY | STATUS | HEADERS,

   # Extensions to fix up (e.g. ".exe" to "%2eexe" to fool the
   # downstream proxies)
   extensions  => [ qw(zip exe jar) ],

   # Who are we.
   version     => '1.00',
  };

# Configuration ends. Do not edit below.
# --------------------------------------

# Reset any external proxy settings.
my $downstream_proxy = 'http://';
$downstream_proxy .=
  $configuration->{proxyuser} . ':' . $configuration->{proxypass} . '@'
  if ($configuration->{proxypass} ne '' and 
      $configuration->{proxyuser} ne '');
$downstream_proxy .= $configuration->{proxyserver};
$downstream_proxy .= ':' . $configuration->{proxyport}
  if ($configuration->{proxyport} ne '');
print("Downstream proxy: $downstream_proxy\n");
for my $e qw(http_proxy https_proxy ftp_proxy) {
    $ENV{$e} = $downstream_proxy;
}
$ENV{no_proxy} = $configuration->{noproxy};

# Package the request header filter.
{
    package MyFilter;
    use base qw(HTTP::Proxy::HeaderFilter);

    sub filter {
	my ($self, $headers, $message) = @_;
	$message->headers->header(User_Agent =>
				  "pproxy/$configuration->{version}");
	my $olduri = $message->uri();
	my $uri = $olduri;
	for my $e (@{ $configuration->{extensions} }) {
	    $uri =~ s{\.$e([^/]*)}{%2e$e$1}g;
	}
	# print("Old uri [$olduri] changed to [$uri]\n");
	$message->uri($uri);
    }
    1;
}

# Set up the logger
my $of;
if (-x '/usr/bin/logger') {
    open($of, '|/usr/bin/logger -t pproxy')
      or die("Cannot start logger pipe: $!\n");
    print("Logging to activity to the system log.\n");
} else {
    open($of, '>>/tmp/pproxy.log')
      or die("Cannot write /tmp/pproxy.log: $!\n");
    print("Logging activity to /tmp/proxy.log.\n");
}

# Instantiate and initialize proxy
my $proxy = HTTP::Proxy->new(port => 3128);
$proxy->push_filter(request => MyFilter->new());
$proxy->logfh($of);
$proxy->logmask($configuration->{loglevel});

# Run tha proxy!
$SIG{PIPE} = 'IGNORE';
print("Contact the proxy on http://localhost:3128.\n");
$proxy->start();</pre>

<div class="box">
Instructions, incase you like this:

<ul>
  
  <li> Copy the listing above and save it to e.g.
    <i>/usr/local/bin/pproxy</i>. </li>

  <li> Make the file executable using
    <i>chmod +x /usr/local/bin/pproxy</i>
  </li>

  <li> Edit the file and fix up the configurations at the top. You
  will need to change the settings for the downstream proxy (proxy
  user, proxy password, proxy server and proxy port), and probably
  you'll want to extend the noproxy list with a few internal hostnames in
  your network. </li>

  <li> Next, fire up the proxy using the command <i>pproxy &amp;</i> <br/>
  Your new proxy is listening to port 3128.</li>

  <li> Configure your programs to use the
  proxy <i>http://localhost:3128</i>. The <i>pproxy</i> process will
  either log to <i>/var/log/messages</i> or to <i>/tmp/pproxy.log</i>
  (depending on the availablility of the
  program <i>/usr/bin/logger</i>), so check there for errors or other
  output. </li>

</ul>

</div>

<p/> <b>Next up, step 3.</b> We reconfigured Maven to talk
to <i>http://localhost:3128</i> as its outgoing proxy, without
supplying proxy credentials ('cuz the above <i>pproxy</i> does that).
We fired up the build process using Maven and - success. Maven fetched
all that it needed (.jar files, .jar.sha1 files and what not) and got
busy.

<p/> We also put the following in the system-wide profile, so that any
wget will work: <pre>export http_proxy=http://localhost:3128</pre>

<p/> That's all! Happy hacking &amp; if you have suggestions - as
ever, <a href="mailto:karel@kubat.nl">drop me a note</a>.

<p/>
<hr/>

<table>
  <tr>
    <td valign="top">
      <img src="/bld/warning.png"/>
    </td>
    <td valign="top">
      <b>August 23rd, update:</b>

      <ul>
	<li> The above shown proxy binds only to the IP address of
	  'localhost' and hence can't be accessed from other machines. If you
	  want to use the proxy from other IP addresses than the local
	  machine, change the <i>HTTP::Proxy</i> constructor to pass a
	  configuration variable <i>host</i>, with value <i>undef</i>. In that
	  case, the proxy will bind to all IP addresses that are available. (The
	  value can also be a specific IP address if you prefer that.) The
	  constructor then becomes:
	  <pre>my $proxy = HTTP::Proxy->new(port => 3128, host => undef);</pre>
	</li>
	
	<li> In order to allow the proxy to serve more than just a few
	  requests at a time, the <i>max_clients()</i> setting can be
	  increased:
	  <pre>my $proxy = HTTP::Proxy->new(port => 3128, host => undef);
$proxy->max_clients(1024);</pre>      
	</li>
	
	<li>Similarly, the downstream timeout (to the NetCache proxy further
	  on) is by default 60 seconds. If you want to shorten it to say 10
	  seconds, add:
	  
	  <pre>$proxy->timeout(10);</pre>
	</li>
	
      </ul>
    </td>

  </tr>
</table>
 
</description>
   </item>
   <item>
    <title>The world will end on May 21, 2011</title>
    <link>http://www.kubat.nl/pages/blogaria/201#201</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I recently visited <i>http://www.wecanknow.com/</i> -- by accident, I swear -- and guess what, on May 21st 2011, Judgement Day will occur (or should've occurred, depending on when you are reading this). That's all fine and well, but <b>what time</b>? What time will the Supreme Being descend onto earth to nuke the shit out of us? Such time resolution of one day just won't do in our modern times. I would prefer the exact time, up to a second precision.

<p/> Maybe I can make an educated guess.

<ul>

  <li> Will the Supreme Being have his morning coffee (or if he's
    British, tea toast and marmelade) and then go about his business,
    as in, "Another boring day at the office ahead, but let's get on
    with it"? In that case I'd expect armageddon 'round ninish. </li>

  <li> Alternatively, he might take care of his e-mails first, do some
    administration, have tea and lunch, and have a nice armageddon
    around half past one. Early-ish in the afternoon, so to speak.
  </li>

  <li> But what if he's from one of the South European countries, or
    from the Carribean, or generally a hot place? Then he'd probably
    prefer to have a siesta first, between say midday and four pm.
    Armageddon would then be rather late in the afternoon.
  </li>

  <li> Or, after leaving the office, he'll pop into his favorite pub,
    have a steak and fries with a couple of pints, get moderately
    pissed, and nuke us. "Rwrright.. lezzhave some armrrag..
    amragged.. nukage." ZAP!
  </li>

  <li> Or maybe even later than that? Just as he's put on his jammies
    and brushes his teeth? "Oh right, almost forgot that there's an
    armageddon scheduled for today. Lucky that I remembered just in
    time!" ZAP.
  </li>

</ul>  

But wait, that's not all. Which timezone is his watch set to? Just a
date simply won't do. The duration of "May 21st" is 48 hours depending
on your location! He might nuke the earth while I'm still on May 20th,
still happily frolicking around and thinking that I have time to
spare. Or he might nuke me while I'm on May 22nd and just having a
beer thinking that all this was just yet another foolish doomday
prediction. Too many open ends.

<p/> Quite arbitrarily I've decided to take my local timezone as
reference. I reckon the Supreme Being will have the decency to respect
my clock. This might not be quite right, but hey, I
need to make an assumption here. In order to help us all estimating
how much time we have left, I have put below a small second-resolution timer.
Incase the Great Zap won't occur, the clock should count up again ;-)

<script type="text/javascript">
var enddate  = new Date(2011, 4, 21, 12, 0, 0, 0);
function showtimer() {
    var thisdate = new Date();
    var diff = Math.round((enddate.getTime() - thisdate.getTime()) / 1000);
    if (diff > 0)
       $('#timer').html('Armageddon will occur in ' + diff + ' seconds'); 
    else 
    	$('#timer').html('Armageddon should have occurred ' + -diff + 
                          ' seconds ago');
    setTimeout('showtimer();', 1000);
}
showtimer();
</script>

<p/>
<center>
  <div id="timer" style="font-size: 12pt; color: red;
			 background-color: lightblue;
			 margin: 5px; padding: 5px;
			 border: 1px solid black">
    <!-- Here the timer will be displayed -->
  </div>
</center>

<p/>
(The clock actually takes the browser's timezone as reference, so
depending on your location, you should hope that the Supreme Being
respects <b>your</b> local clock.)
 
</description>
   </item>
   <item>
    <title>Hiding or showing a textbox with image animation using JQuery</title>
    <link>http://www.kubat.nl/pages/blogaria/200#200</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 More eye candy in the browser!

<p/> Here's a very quick description how you can hide or show a text
box in a browser, with image animation in a title bar that suggests
that the box can be opened or closed.

<p/> Here are some concepts:
<ul>

  <li> Internally we'll use <a href="http://jquery.com/"
  target="_blank">JQuery</a> to show or hide page content. </li>
  
  <li> We'll need an outer div which will be always visible. In this,
  there will be... </li>

  <li> A title div, also always visible. Clicking an image in the
  title div toggles the visibility of... </li>

  <li> A content div, which is either visible or not. </li>

</ul>

<h3>Typical usage</h3>

Here is a small example. For visibility, the outer div has a border
around it. There's a small arrow in the title to toggle the visibility
of the contents. The shown arrow is the
file <i>/img/arrow-down.png</i>, it's a transparent arrow that will
look right on any background. Once the content hides, the image
changes to <i>/img/arrow-right.png</i> (If you want, get the images
from my site. I made them, and they are <b>not</b> copyrighted. Use
them however you like.) Try it out, click on the arrow below.

<script>
function togglebox(image_id, content_id) {
    if ($('#' + content_id).is(':visible')) {
        $('#' + image_id).attr('src', '/img/arrow-right.png');
	$('#' + content_id).hide('fast');
    } else {
        $('#' + image_id).attr('src', '/img/arrow-down.png');
	$('#' + content_id).show('fast');
    }
}
</script>

<p/>
<div class="box">
  <div style="background-color: #d0d0d0">
    <img id="arrow_img" src="/img/arrow-down.png"
	 onclick="togglebox('arrow_img', 'content_div');"/>
    <b>Click the arrow to hide or show contents.</b>
  </div>
 <div id="content_div">
    Lorem ipsum dolor sit amet, aliquam dolor, viverra et in, amet
    lacus. Felis elit ligula integer, dolor lacus, tellus integer duis
    ut amet, metus et aenean. Iaculis mollis vestibulum odio amet duis
    quis, sodales nulla tellus enim proin, scelerisque praesent erat
    integer felis dictum et, nam vestibulum dui eros, ut adipiscing
    porttitor in. Nunc nibh malesuada ut aliquam cursus, enim
    fermentum cursus aliquam pretium lorem, consequat interdum
    dictumst placerat pellentesque, vel volutpat eget eu, tortor quis
    lacus metus. Donec cras aliquam nulla dictumst magna, vulputate
    lacus erat, augue orci ut sit pellentesque condimentum aliquet,
    amet sodales sit egestas praesent. Fringilla ultricies
    consectetuer felis, turpis nulla blandit cursus eros purus velit,
    metus nec urna, diam mi esse consectetuer duis sem morbi. Eros
    semper in eu, mauris magna vitae sed mi vitae, sed non porta wisi,
    nam habitant, vivamus fermentum sodales enim nam. Vestibulum id
    risus duis omnis sed pellentesque, cursus magna egestas nunc in,
    pulvinar sed sit ante luctus ut, rutrum placerat malesuada purus
    lacus erat, nam nulla porttitor vel nibh. Massa sit sem elementum
    pretium. Nulla sed pede a, leo eu libero nam tellus aenean, mus
    lobortis semper leo arcu massa sed, non vero.
  </div>
</div>
     
Right. Onward to the code. First of all, you will need JQuery, a
JavaScript library, which is included in the head section of the
page. You can get your copy of <i>jquery.js</i>
at <a href="http://jquery.com/" target="_blank">jquery.com</a>. (The
downloaded copy might have a filename like <i>jquery-1.4.2.min.js</i>,
i.e., with a version ID etc. in it. For practical purposes, I'm just
referring to it as <i>jquery.js</i>.)

<pre>
&lt;html&gt;
  &lt;head&gt;
    &lt;script type="text/javascript" src="/where/ever/jquery.js"&gt;
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt; &lt;!-- body content comes here --&gt; &lt;/body&gt;
&lt;/html&gt;
</pre>

Next, you'll need a text box. Here's what comes in the body.

<pre>
&lt;!-- Outer box. We give it a 1pt border to make it stand out. --&gt;  
&lt;div style="border: 1pt"&gt;

  &lt;!-- Title box. We give it a slightly different back ground color to
       to make it stand out. Inside is the image of the arrow (initially:
       down), with an onclick handler to toggle (see below). Also there
       is a box title. The image must have some id, in this example it is
       arrowimage. --&gt;  
  &lt;div style="background-color: #d0d0d0"&gt;
    &lt;img id="arrowimage" src="/img/arrow-down.png"
	 onclick="togglebox('arrowimage', 'contentbox');"/&gt;
    &lt;b&gt;Click the arrow to hide or show the contents.&lt;/b&gt;
  &lt;/div&gt;

  &lt;!-- The content box. It must have an id, in this example it is 
       contentbox. Note that the above id of the arrow and the id
       this box are used in the call to the function togglebox().
       We also give it a nice background color. --&gt;
  &lt;div id="contentbox" style="background-color: #e0e0e0"&gt;
    Lorem ipsum dolor sit amet, ..... non vero.
  &lt;/div&gt;
&lt;/div&gt;
</pre>

Right. The only thing that remains is the Javascript
function <i>togglebox()</i>. It works as follows:

<ul>
  <li> It expects two arguments: the ID of the image of a box, and the
  ID of the content div of a box. </li>
  
  <li> When the content div is visible, then the image is swapped
  to <i>/img/arrow-right.png</i> and the content is hidden. </li>

  <li> When the content div is hidden, then the image is swapped
  to <i>/img/arrow-down.png</i> and the content is shown. </li>
  
</ul>

Here it is.

<pre>
&lt;script&gt;
function togglebox(image_id, content_id) {
    if ($('#' + content_id).is(':visible')) {
        $('#' + image_id).attr('src', '/img/arrow-right.png');
	$('#' + content_id).hide('fast');
    } else {
        $('#' + image_id).attr('src', '/img/arrow-down.png');
	$('#' + content_id).show('fast');
    }
}
&lt;/script&gt;
</pre>

<h3>An initially hidden textbox</h3>

The text box can be initially made hidden, so that it "unfolds"
when a user clicks the arrow. The easiest way to do that, is to draw
the box as shown above, but to run <i>togglebox()</i> just once to
hide it. From then on the user can take over to show it. The following
box should be initially hidden, but you can click on the arrow to show
its contents:

<div class="box">
  <div style="background-color: #d0d0d0">
    <img id="hiddenboximg" src="/img/arrow-down.png"
	 onclick="togglebox('hiddenboximg', 'hiddenboxcontent');"/>
    <b>Click the arrow to hide or show contents.</b>
  </div>
 <div id="hiddenboxcontent">
    Lorem ipsum dolor sit amet, aliquam dolor, viverra et in, amet
    lacus. Felis elit ligula integer, dolor lacus, tellus integer duis
    ut amet, metus et aenean. Iaculis mollis vestibulum odio amet duis
    quis, sodales nulla tellus enim proin, scelerisque praesent erat
    integer felis dictum et, nam vestibulum dui eros, ut adipiscing
    porttitor in. Nunc nibh malesuada ut aliquam cursus, enim
    fermentum cursus aliquam pretium lorem, consequat interdum
    dictumst placerat pellentesque, vel volutpat eget eu, tortor quis
    lacus metus. Donec cras aliquam nulla dictumst magna, vulputate
    lacus erat, augue orci ut sit pellentesque condimentum aliquet,
    amet sodales sit egestas praesent. Fringilla ultricies
    consectetuer felis, turpis nulla blandit cursus eros purus velit,
    metus nec urna, diam mi esse consectetuer duis sem morbi. Eros
    semper in eu, mauris magna vitae sed mi vitae, sed non porta wisi,
    nam habitant, vivamus fermentum sodales enim nam. Vestibulum id
    risus duis omnis sed pellentesque, cursus magna egestas nunc in,
    pulvinar sed sit ante luctus ut, rutrum placerat malesuada purus
    lacus erat, nam nulla porttitor vel nibh. Massa sit sem elementum
    pretium. Nulla sed pede a, leo eu libero nam tellus aenean, mus
    lobortis semper leo arcu massa sed, non vero.
  </div>
</div>
<script>
  togglebox('hiddenboximg', 'hiddenboxcontent');
</script>

Here's how this looks in the code:

<pre>
&lt;!-- Outer box --&gt;
&lt;div&gt;
  &lt;!-- Title box and content box go here, just as in the above
       example. --&gt;
&lt;/div&gt;
&lt;!-- Now we initially hide the textbox. The image id and content id
     must match the id's in the divs. --&gt;
&lt;script type="text/javascript"&gt;
  togglebox('arrowimage', 'contentbox');
&lt;/script&gt;
</pre>

<h3>Playing around with a floating box</h3>

<div class="box" style="float: right; width: 200pt">
  <div style="background-color: #d0d0d0">
    <img id="floatboximg" src="/img/arrow-down.png"
	 onclick="togglebox('floatboximg', 'floatboxcontent');"/>
    <b>Same thing, but a floating box.</b>
  </div>
  <div id="floatboxcontent">
    Lorem ipsum dolor sit amet, aliquam dolor, viverra et in, amet
    lacus. Felis elit ligula integer, dolor lacus, tellus integer duis
    ut amet, metus et aenean. Iaculis mollis vestibulum odio amet duis
    quis, sodales nulla tellus enim proin, scelerisque praesent erat
    integer felis dictum et, nam vestibulum dui eros, ut adipiscing
    porttitor in. Nunc nibh malesuada ut aliquam cursus, enim
    fermentum cursus aliquam pretium lorem, consequat interdum
    dictumst placerat pellentesque, vel volutpat eget eu, tortor quis
    lacus metus.
  </div>
</div>

The same concept can be re-used on the same page, as long as the image
id and content div id are unique per textbox. As with any div, the
textbox can be placed inline with text, just by adding a style, as
in: <i> &lt;div style="float: right; width: 200pt"&gt;</i> There are
lots of possibilities to play around with.

<p/> Have fun! And as ever, if you have neat additions
- <a href="mailto:karel@kubat.nl">drop me a note</a>.

 
</description>
   </item>
   <item>
    <title>Manipulating browser cookies using Javascript</title>
    <link>http://www.kubat.nl/pages/blogaria/199#199</link>
    <pubDate>Fri, 27 Apr 12 21:41:00 +0200</pubDate>
    <description>
 I've had to manipulate cookies in Javascript a number of times now. I've had so much code distributed over so many separate projects, that I've decided to collect it into one sort-of comprehensive set of functions. Here's the outcome.

<ul>
  <li> If you're interested, the file <i>cookies.js</i> can be
    downloaded <a href="/cookiesjs/cookies.js"><b>here</b></a>. </li>

  <li> As with most things on this site: you're free to use it as you
  see fit. And if you have nice and useful additions
  - <a href="mailto:karel@kubat.nl">let me know</a>! </li>

  <li> Here's a short synopsis (from the top of the source file):

<pre></pre></li>

  <li> If you want to see a quick test with some explanation, which
    runs the test in your browser: there is a short test below. You
    can also get a stand-alone test file which does the same as
    <a href="/cookiesjs/test.html" target="_blank">test.html</a>.
    </li>
</ul>

<script type="text/javascript" src="/cookiesjs/cookies.js"></script>

    <hr/>
    <h3>Initializing</h3>
    The code is contained in a file <i>cookies.js</i> which must be
    sourced:    
    <pre>
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;JavaScript Cookie Functions Test&lt;/title&gt;
    &lt;script type="text/javascript" src="cookies.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt; &lt;!-- Body goes here --&gt; &lt;/body&gt;
&lt;/html&gt;  
    </pre>

    <hr/>
    <h3>Setting Cookies</h3>
    For example: This sets cookies named <i>test0</i>
    through <i>test9</i> having values <i>value_of_test_0</i> and so on.
    <pre>
for (var i = 0; i < 10; i++)
    cookie_set('test' + i, 'value_of_test_' + i, 1, '/');
		    </pre>

    <script type="text/javascript">
      for (var i = 0; i < 10; i++)
          cookie_set('test' + i, 'value_of_test_' + i, 1, '/');
    </script>

    <hr/>
    <h3>Getting the value of a given cookie</h3>
    This returns the value of a given cookie, e.g. <i>test4</i>:
    <pre>
document.write('The value of cookie test4 is: ' +
               cookie_get('test4'));
    </pre>

    <i>
      <script type="text/javascript">
       document.write('The value of cookie test4 is: ' +
                      cookie_get('test4'));
      </script>
    </i>

    <hr/>
    <h3>Listing all cookies</h3>
    Function <i>cookie_names()</i> returns an array of the names of all
    cookies:

    <pre>
document.write('&lt;ul&gt;'); 
var cookies = cookie_names();
for (var i = 0; i &lt; cookies.length; i++)
    document.write('&lt;li&gt;Cookie &lt;i&gt;' + cookies[i] + '&lt;/i&gt;' +
	           ' has value ' + cookie_get(cookies[i]));
document.write('&lt;/ul&gt;');
    </pre>

    <i>
      <script type="text/javascript">
	document.write('<ul>');
	  var cookies = cookie_names();
	  for (var i = 0; i < cookies.length; i++)
             document.write('<li>Cookie <i>' + cookies[i] + '</i>' +
	 	 	    ' has value ' + cookie_get(cookies[i]));
	document.write('</ul>');
    </script>
    </i>

    <hr/>
    <h3>Deleting one cookie</h3>
    Function <i>cookie_delete()</i> removes a given cookie. It is
    exactly the same as calling <i>cookie_set()</i> with value ''
    (empty string). For example, this kills cookie <i>test1</i>:
    
    <pre>
cookie_delete('test1');      
document.write('&lt;ul&gt;'); 
var cookies = cookie_names();
for (var i = 0; i &lt; cookies.length; i++)
    document.write('&lt;li&gt;Cookie &lt;i&gt;' + cookies[i] + '&lt;/i&gt;' +
	           ' has value ' + cookie_get(cookies[i]));
document.write('&lt;/ul&gt;');
    </pre>
    <i>
      <script type="text/javascript">
	cookie_delete('test1');
	document.write('<ul>');
	var cookies = cookie_names();
	for (var i = 0; i < cookies.length; i++)
             document.write('<li>Cookie <i>' + cookies[i] + '</i>' +
	 	 	    ' has value ' + cookie_get(cookies[i]));
	document.write('</ul>');
     </script>
    </i>

    <hr/>
    <h3>Deleting a number of cookies</h3>
    Function <i>cookies_delete()</i> (mind the <b>s</b>) deletes a
    "blacklist" of cookies. E.g., the following kills
    cookies <i>test7</i> and <i>test9</i>:
    <pre>
cookies_delete(new Array('test7', 'test9')); 
document.write('&lt;ul&gt;'); 
var cookies = cookie_names();
for (var i = 0; i &lt; cookies.length; i++)
    document.write('&lt;li&gt;Cookie &lt;i&gt;' + cookies[i] + '&lt;/i&gt;' +
	           ' has value ' + cookie_get(cookies[i]));
document.write('&lt;/ul&gt;');
    </pre>
    <i>
      <script type="text/javascript">
	cookies_delete(new Array('test7', 'test9'));
	document.write('<ul>');
	var cookies = cookie_names();
	for (var i = 0; i < cookies.length; i++)
             document.write('<li>Cookie <i>' + cookies[i] + '</i>' +
	 	 	    ' has value ' + cookie_get(cookies[i]));
	document.write('</ul>');
     </script>
    </i>

    <hr/>
    <h3>Deleting all cookies but a few</h3>
    Function <i>cookies_delete_except()</i> (mind the <b>s</b>)
    deletes cookies except when they are in a "whitelist". 
    E.g., the following kills all cookies but <i>test5</i> and
    <i>test6</i>:
   <pre>
cookies_delete_except(new Array('test5', 'test6'));  
document.write('&lt;ul&gt;'); 
var cookies = cookie_names();
for (var i = 0; i &lt; cookies.length; i++)
    document.write('&lt;li&gt;Cookie &lt;i&gt;' + cookies[i] + '&lt;/i&gt;' +
	           ' has value ' + cookie_get(cookies[i]));
document.write('&lt;/ul&gt;');
    </pre>
    <i>
      <script type="text/javascript">
	cookies_delete_except(new Array('test5', 'test6')); 
	document.write('<ul>');
	var cookies = cookie_names();
	for (var i = 0; i < cookies.length; i++)
             document.write('<li>Cookie <i>' + cookies[i] + '</i>' +
	 	 	    ' has value ' + cookie_get(cookies[i]));
	document.write('</ul>');
     </script>
    </i>
 
</description>
   </item>
   <item>
    <title>Survival of the fittest book</title>
    <link>http://www.kubat.nl/pages/blogaria/198#198</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 On my holiday I read (no, I devoured) "The Greatest Show on Earth" by
Richard Dawkins. A really marvellous book which tells evolutionary
stories of nature all over the world, digs into some aspects of
geology and fossiles, and of course: explains how silly the
Creationinst views are, when you regard all the evidence. Dawkins'
main point is that "the theory of evolution" isn't a theory in the
sense that it might or might not be true: it's a theory in the sense
that it's accepted and true, and the "theoretical" part is the
scientific explanation, as in "theory of gravity". Not many people
will dispute the existence of gravity, because there's the word
"theory" attached to it.

<p/>
<center>
  <img src="/bld/RD-tgson/RD-tgson1.jpg"/>
  <img src="/bld/RD-tgson/RD-tgson2.jpg"/>
</center>

<p/> I can highly recommend this book. Many of the concepts might be
already known to you (especially if you're
a <a href="/pages/blogaria/197#197">Pastafarian</a>), and Dawkins is a
great storyteller who talks about the genious of Darwin and who
brilliantly makes his point.

<p/> There's just one thing about this book. My soft cover copy didn't
survive the beach life, so it didn't do too well on spreading its
ideas beyond just one individual. I suspect that a hard cover copy
would be more fit in projecting its content into the world... might
there be a pseudo-evolutionary pressure on books that favors hard
covers? Or, might there be a "ideological" evolutionary pressure that
disfavors ideas expressed in soft covers? Hmmm... I wonder what the
creationist viewpoint is on this matter!

 
</description>
   </item>
   <item>
    <title>Pastafarians in Spain</title>
    <link>http://www.kubat.nl/pages/blogaria/197#197</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  During my last week's holiday in Spain, I saw this sign in Llan&ccedil;a (which is north of Barcelona and very close to the French border:):

  <p/>
  <img src="/bld/LaTavernaDelPirata.jpg"/>

  <p/>
  I find it very comforting that there's a strong chapter of <a href="http://en.wikipedia.org/wiki/Pastafarian" target="_blank">Pastafarians</a> in this part of spain.

</center>
 
</description>
   </item>
   <item>
    <title>You have two sheep</title>
    <link>http://www.kubat.nl/pages/blogaria/196#196</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/TwoSheep.jpg" class="floatright"/>This was forwarded to me by my bro' in law. Another one of those
lists, but quite good tbh. LOL!

<ul>

  <li>SOCIALISM: You have 2 sheep, and you give one to your neighbour.<p/></li>
  
  <li>COMMUNISM: You have 2 sheep. The State takes both and gives you
    some wool. <p/></li>

  <li>FASCISM: You have 2 sheep. The State takes both and sells you some wool.<p/></li>

  <li>NAZISM: You have 2 sheep. The State takes both and shoots you.<p/></li>

  <li>BUREAUCRATISM: You have 2 sheep. The State takes both, shoots
    one, shears the other, then throws the wool away...<p/></li>

  <li>TRADITIONAL CAPITALISM: You have two sheep. You sell one and buy
    a ram. Your herd multiplies, and the economy grows. You sell them and retire on 
    the income.<p/></li>

  <li>SURREALISM: You have two giraffes. The government requires you
    to take harmonica lessons.<p/></li> 

  <li>AN AMERICAN CORPORATION: You have two sheep. You sell one, and
    force the other to produce the wool of four sheep. Later, you hire a
    consultant to analyse why the sheep has dropped dead.<p/></li>

  <li>ENRON VENTURE CAPITALISM: You have two sheep. You sell three of
    them to your publicly listed company, using letters of credit opened
    by your brother-in-law at the bank, then execute a debt/equity swap
    with an associated general offer so that you get all four sheep
    back, with a tax exemption for five sheep. The wool rights of the
    six sheep are transferred via an intermediary to a Cayman Island
    Company secretly owned by the majority shareholder who sells the
    rights to all seven sheep back to your listed company. The annual
    report says the company owns eight sheep, with an option on one
    more. Sell one sheep to buy a new president of the United States,
    leaving you with nine sheep. No balance sheet provided with the
    release. The public buys your ram.<p/></li>

  <li>THE ANDERSEN MODEL: You have two sheep. You shred them.<p/></li>

  <li>A FRENCH CORPORATION: You have two sheep. You go on strike,
    organise a riot, and block the roads, because you want three sheep.<p/></li>

  <li>A JAPANESE CORPORATION: You have two sheep. You redesign them so
    they are one-tenth the size of an ordinary sheep and produce twenty
    times the wool. You then create a clever sheep cartoon image called
    'baakimon' and market it worldwide.<p/></li>

  <li>A GERMAN CORPORATION: You have two sheep. You re-engineer them
    so they live for 100 years, eat once a month, and shear
    themselves.<p/></li>
  
  <li>AN ITALIAN CORPORATION: You have two sheep, but you don't know
    where they are. You decide to have lunch.<p/></li>

  <li>A RUSSIAN CORPORATION: You have two sheep. You count them and
    learn you have five sheep. You count them again and learn you have 42
    sheep. You count them again and learn you have 2 sheep. You stop
    counting sheep and open another bottle of vodka.<p/></li>

  <li>A SWISS CORPORATION: You have 5000 sheep. None of them belong to
    you. You charge the owners for storing them. <p/></li>

  <li>A CHINESE CORPORATION: You have two sheep. You have 300 people
    shearing them. You claim that you have full employment, and high sheep
    productivity, and arrest the newsman who reported the real
    situation. <p/></li>

  <li>AN INDIAN CORPORATION: You have two sheep. You worship
    them.<p/></li>

  <li>IRAQI CORPORATION: Everyone thinks you have lots of sheep. You
    tell them that you have none. No-one believes you, so they bomb the
    **** out of you and invade your country. You still have no sheep, but
    at least now you are part of a Democracy....<p/></li>

  <li>WELSH CORPORATION: You have two sheep. The one on the left looks
    very attractive.<p/></li>

  <li>AUSTRALIAN CORPORATION: You have two sheep. Business seems
    pretty good. You close the office and go for a few beers to
    celebrate.<p/></li>

</ul>

(I have no idea who originally wrote this. But I've a feeling that the
author was a non-Welsh traditional capitalist.)
 
</description>
   </item>
   <item>
    <title>Highway bank fire</title>
    <link>http://www.kubat.nl/pages/blogaria/195#195</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Suddenly all motion stopped. Apparently there was a highway bank fire
ahead, just some grass that had caught on fire and needed
extinguishing. We stood there for hours, no movement in either
direction. And, no softdrinks truck in sight that an angry mob might raid.

<p/>

<center>
  <img src="/bld/hw-bank-fire/TrafficJam1.jpg"/>
  <img src="/bld/hw-bank-fire/TrafficJam2.jpg"/>

  <p/>

  After a while some people just gave up and took a nap.

  <p/>
  <img src="/bld/hw-bank-fire/TrafficJam3.jpg"/>
</center>

<p/> Finally the police actually had all cars turn around and drive
off into the wrong direction, so all could get off the highway at the
next ramp. This was the longest jam ever. Honest. It took sooooo long
I even had to write it up. I might have to discuss this with my
therapist. 

 
</description>
   </item>
   <item>
    <title>Setting up a remote git repository</title>
    <link>http://www.kubat.nl/pages/blogaria/194#194</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I always forget how to set up remote git repositories..  So here's a <i>memo to self</i>.

<table>
  
  <tr>
    <th width="50%" style="background: lightgray"><b>Local machine (developer)</b></th>
    <th width="50%" style="background: lightgray"><b>Remote server (git server)</b></th>
  </tr>

  <tr>
    <td style="background: #f0f0f0">
     <b>Setting up the local git</b>
      <pre>
	# Set up new repository
	git init
	# Add all files
	git add -A
	# Commit to the local repository
	git commit -a -m 'initial git commit'
      </pre>
    </td>
   <td style="background: #f0f0f0">
    </td>
 </tr>

  <tr>
    <td style="background: #f0f0f0">
    </td>
    <td style="background: #f0f0f0">
      <b>Setting up the remote git</b>
      <pre>
	# Go to remote server
	ssh gituser@remote_server
	cd /home/of/repositories
	mkdir project
	cd project
	# Initialize a bare repository
	git init --bare
      </pre>
    </td>
  </tr>

  <tr>
    <td style="background: #f0f0f0">
      <b>Hooking up the remote git</b>
      <pre>
	git remote add remote_server ssh://gituser@remote_server/home/of/repositories/project
      </pre>
    </td>
    <td style="background: #f0f0f0">
    </td>
  </tr>

  <tr>
    <td style="background: #f0f0f0">
      <b>Syncing local git to remote</b>
      <pre>
	git push remote_server master
      </pre>
      Repeat as often as you feel like..
    </td>
    <td style="background: #f0f0f0">
    </td>
  </tr>

  <tr>
    <td style="background: #f0f0f0">
      <b>Syncing remote git to local</b>
      <pre>
	# Clean start
	mkdir /tmp/project
	cd /tmp/project
	# Git initializers
	git init
	git remote add remote_server ssh://gituser@remote_server/home/of/repositories/project
	# Pull from remote
	git pull remote_server master
      </pre>
   </td>
    <td style="background: #f0f0f0">
    </td>
  </tr>

</table>
 
</description>
   </item>
   <item>
    <title>Bye bye trusted old Macbook</title>
    <link>http://www.kubat.nl/pages/blogaria/193#193</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/mac/oldmac.jpg"/ class="floatright"/>
A few days ago my trusted ol' 17" Macbook Pro broke. It broke good.
The vido card went berserk, showed some weird patterns and then just
went dead. No more output. So now what? After staring at the screen
for a few seconds, I first of all composed a poem.

<p/>
<i>
  <quote>
    Blackness engulfs the tiny spots <br/>
    Where pixels would shine <br/>
    They sparkle no more. <br/>
    You are toast.
  </quote>
</i>

  <p/>
  The Macbook was beyond reasonable repair. Well, you can repair
  anything of course, but replacing the video card would mean replacing
  the entire motherboard, which doesn't really make sense doing to a
  laptop that's been heavily used for years, day in day out. Ah the
  sadness. But alas, it was time to say farewell to my trusted lappie...

Yep, it was time to authanise it. But first, some salvage work for the
hard disk. For this I needed a small Phillips screwdriver (which most
of us have), and a tiny Torque-6 screwdriver (which I had to go buy,
well actually I got a precision screwdriver set). I also got a casing
for a 2.5" SATA disk, so I could make a nice external USB disk out of
the old laptop disk.

<p/>Thus equipped, I unscrewed the body and could lift the keyboard.
There are loads of screws that hold the body together, and all must
go!

<table>
  <tr>
    <td valign="top" style="background:#f0f0f0" width="410">
      <hr/>
     <img src="/bld/mac/screwdrivers.jpg"/><br/>
      <i>Necessary equipment. Note the T6 torque, the case can't be
      disassembled without it.</i>
   </td>
    <td valign="top" style="background:#f0f0f0" width="410">
      <hr/>
     <img src="/bld/mac/liftkbd.jpg"/><br/>
      <i>Once the screws are out, the keyboard can be lifted. <br/>
	The hard disk is at the left lower corner just under my hand.</i>
    </td>
  </tr>
  <tr>
    <td valign="top" style="background:#f0f0f0">
      <hr/>
      <img src="/bld/mac/hdusocket.jpg"/><br/>
      <i>The hard disk is removed. An empty SATA socket proves it..</i>
   </td>
    <td valign="top" style="background:#f0f0f0">
      <hr/>
      <img src="/bld/mac/enclosure.jpg"/><br/>
      <i>Whee! The old disk in its new habitat.</i>
   </td>
</table>

<p/> It left me with a few spare parts (battery and 4Gb of RAM) and
basically a broken motherboard, used-up aluminium casing, but a good
screen. Anyone interested? But, end of the day.. a new 17" Macbook Pro
was happily restoring files from the old disk. It's my new development
machine now and the external USB disk has found a new home as one of
my TimeMachine backup media.

<p/>
<img src="/bld/mac/twomacs.jpg"/>
	   
<p/> On the upside:
<ul>
  <li>Got to buy a new precision screwdriver set.</li>
  <li>New Macbook Pro really does look sexier.</li>
  <li>Got a new USB hard disk.</li>
  <li>170fps in Stormwind....</li>
</ul>
 
</description>
   </item>
   <item>
    <title>John Cleese on Football</title>
    <link>http://www.kubat.nl/pages/blogaria/192#192</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 There's a very important game coming up this afternoon - Netherlands
vs. Slovakia. I'm talking football of course.

<p/> This brings John Cleese to mind and his famous rant on "football
vs. soccer". The man is <i>the</i> personification of sarcasm. John
Cleese always deserves re-blogging...

<p/>

<center>
<object width="640" height="385">
  <param name="movie"
	 value="http://www.youtube.com/v/2sD_8prYOxo&hl=en_US&fs=1&">
  </param>
  <param name="allowFullScreen"
	 value="true">
  </param>
  <param name="allowscriptaccess"
	 value="always">
  </param>
  <embed src="http://www.youtube.com/v/2sD_8prYOxo&hl=en_US&fs=1&"
	 type="application/x-shockwave-flash"
	 allowscriptaccess="always"
	 allowfullscreen="true"
	 width="640"
	 height="385">
  </embed>
</object>
</center>
 
</description>
   </item>
   <item>
    <title>ABN Amro and the Pathetic Customer Service Dept.</title>
    <link>http://www.kubat.nl/pages/blogaria/191#191</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <!-- <img src="/bld/ABN-Amro-Donkey.jpg" class="floatright"/> -->

<div style="float: right;
	     font-size: 8pt;
	     background-color: #e0e0ee;
	     width: 440px;
	     margin: 5px; padding: 5px; border: 1px solid black;">
  <center>
    <img src="/bld/ABN-Amro-Donkey.jpg"/>
    <br/>
    <i>"I'll be good for you. Trust me."</i>
  </center>
</div>

My mum and dad had a shared account at the Dutch ABN-Amro Bank. They'd
have some savings in that account, my dad's pension would arrive here,
and they'd pay some bills from this account.

<p/> Then, six months ago, my mum suddenly passed away. For all the
obvious reasons it took a while before our family got around to
sorting out the less important administrative issues, such as this
bank account. But eventually my sister and my dad decided that it was
about time to get this over with. So she called ABN-Amro, and was told
that my dad would have to show up in person to change the account
ownership to only one person - to him. And would they bring ID's and
the death certificate for my mum?

<p/> So, being a good citizen, my sister took all the necessary
paperwork and my 86 year old dad to the ABN-Amro building in The
Hague. At the general information desk she told her story - that my
mum had passed away, and that therefore they wanted to change the
account ownership. She was promptly told that this was only possible
at another ABN-Amro building in The Hague.

<p/> Still being a good citizen, my sis stuffed my dad into a taxi and
together they went off to that other building. Here, again at the
information desk, she repeated everything. And was told that she would
have to arrange this at a given bank desk, amidst other desks with
other customers who were withdrawing cash or doing whatever they did.
Mind, these are the teller-like desks where you stand around
explaining your question to a bank employee. These are not the
old-fashioned large-space desks of old times where one would sit down
and talk.

<p/> Now, standing around for some time in front of a desk in a bank hall
with my 86 year old dad was not an option at that time, and I'm dead
sure that my sis' middle finger was just itching. She took my dad,
turned around, and left the building.

<p/> Here's my conclusion: <b>ABN-Amro's customer service
  sucks donkey. Bigtime.</b>

<div style="background-color: #e0e0e0;
	    margin: 5px; padding: 5px; border: 1px solid black;">
  
<p/> I've got a few tips for ABN-Amro personnel. Just have a
look at the below questions when a customer is talking to you, and
answer them with a yes or no:

<ol>

  <li>Have the customers come to your bank voluntarily, while they
    actually weren't obliged to do so?</li>

  <li>Does their story involve the death of a loved one?</li>

  <li>Is there a person present who's obviously aged and not very
    agile?</li> 

</ol>

If the answer to any of the above is <b>yes</b>, then proceed as
follows.

<ol>

  <li> Get the customers into one of the private rooms and sit them
  down. Yes, you have those rooms, you use them when people open
  accounts or sign contracts. You can use them for these occasions
  too.</li>

  <li>Get them a cup of coffee. Make them comfortable. Show some
  interest. </li>

  <li> Sort out their problem, or their question, or whatever they
  came with. If this involves transferring information to another
  building, then handle it. You can get the necessary information to a
  different bank location much easier than your customers can. You've
  got internal mail, your customers don't. </li>

  <li> Behave as if <i>they were paying your salary</i>. Hey,
  actually.. they <b>are</b> paying your salary. </li>

</ol>
</div>

<p/> I'm fairly sure that this account will pretty soon cease to
exist. Suddenly ABN-Amro will receive an order to transfer all funds
to an account owned by my dad with an other bank, and to leave zero
euro's in this ABN-Amro account. After that they can stick this
account wherever they please. Wanna bet?
 
</description>
   </item>
   <item>
    <title>Wally does not like criticism</title>
    <link>http://www.kubat.nl/pages/blogaria/190#190</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  Wally doesn't like criticism.

  <p/>
  <img src="/bld/Dilbert-Wally-Criticism.gif"/>
  <p/>

  If Wally were a gamer, he'd add "p0wn3d".
</center>
  
 
</description>
   </item>
   <item>
    <title>Soccermatch Netherlands vs Denmark</title>
    <link>http://www.kubat.nl/pages/blogaria/189#189</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today at 13:30h was the soccer match between the Netherlands and
Denmark. The first match of the Dutch team, so of course - everyone
was excited! Unfortunately there was the daily drag of work. But, at
my customer's location, a big screen was put up, where all who were
interested, could watch. It was a really nice experience - and the
Dutch team wan two-nil which makes it even better. The pictures don't
convey the volume of the cheers that went up during each goal, but
trust me, it was deafening...

<p/>
<hr/>
<center>
  <img src="/bld/Office-Soccer-01.jpg"/>
</center>

<p/>
<hr/>
<center>
  <img src="/bld/Office-Soccer-02.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Lazy Cat</title>
    <link>http://www.kubat.nl/pages/blogaria/188#188</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Some have work. Some have worries. Some have responsibilities.
Others don't. They're just lazing on a sunday afternoon. And waiting
'till I bring the next bowl of noms. 

<p/>
<center>
<img src="/bld/James-00.jpg"/><hr/><p/><img src="/bld/James-01.jpg"/><hr/><p/><img src="/bld/James-02.jpg"/><hr/><p/><img src="/bld/James-03.jpg"/><hr/><p/></center>
 
</description>
   </item>
   <item>
    <title>Reading public Buzz using the Google API</title>
    <link>http://www.kubat.nl/pages/blogaria/187#187</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/thoughtful.jpg" class="floatright"/>
Here's a neat little thing that I've been playing around with this
weekend. Google offers an API for its Buzz social network, and it's
really very easy to use it - all you need is web access, an HTTP
client, and you need to know how to parse the API results.

<p/> Here's now to get the most recent public Buzz entries for a given
user. Google offers the list
at <i>http://www.googleapis.com/buzz/v1/activities/USERNAME/@public</i>,
where of course the USERNAME must be changed into something
meaningful. The default format is XML (yech), but
adding <i>alt=json</i> fixes that. The default number of returned
entries is 20, but that can be limited by e.g. <i>max-results=5</i>.

Here's an example of my latest one Buzz (the listing gets kind of long
when you fetch more, and I replaced some too long URL's with ... and
inserted arbitrary newlines):

<pre>
  bash$ curl 'www.googleapis.com/buzz/v1/activities/kkubat/@public?alt=json&max-results=1'

  {"data":{"kind":"buzz#activityFeed","links":{"next":[{"href":
  "https://www.googleapis.com/buzz/v1/activities/108588487512525984185/@public?..."}],
  "self":[{"href":"https://www.googleapis.com/buzz/v1/activities/108588487512525984185/@public?alt\u003djson",
  "type":"application/json"}],"hub":[{"href":"http://pubsubhubbub.appspot.com/"}]},
  "title":"Google Buzz Public Feed","updated":"2010-06-08T10:50:01.127Z",
  "id":"tag:google.com,2010:buzz-feed:public:posted:108588487512525984185","items":[{"kind":
  "buzz#activity","title":"Sushi Saturday - great fun for all, pics at
  http://www.kubat.nl/pages/blogaria/185#185. Plus,
  Ste...","published":"2010-06-07T09:35:17.000Z","updated":
  "2010-06-07T09:35:17.782Z","id":"tag:google.com,2010:buzz:z12lhzwoyvz5z1qfl23rx1vztyrdzdyue",
  "links":{"liked":[{"href":
  "https://www.googleapis.com/buzz/v1/activities/108588487512525984185/@self/tag:...",
  "type":"application/json","count":0}],"alternate":[{"href":
  "http://www.google.com/buzz/108588487512525984185/L247NmucVAq",
  "type":"text/html"}],"replies":[{"href":
  "https://www.googleapis.com/buzz/v1/activities/108588487512525984185/@self/tag:...",
  "type":"application/json","count":0,"updated":"2010-06-07T09:35:17.782Z"}],"self":[{"href":
  "https://www.googleapis.com/buzz/v1/activities/108588487512525984185/@self/tag:..."}
  ]},"actor":{"id":"108588487512525984185","name":"Karel
  Kubat",
  "profileUrl":"http://www.google.com/profiles/kkubat","thumbnailUrl":
  "http://www.google.com/s2/photos/public/AIbEiAIAAABDCLmj9e-4_JuYdyILdmNhcmRfcGhv..."},
  "verbs":["post"],"object":{"type":"note","content":"Sushi
  Saturday - great fun for all, pics at \u003ca
  href\u003d\"http://www.kubat.nl/pages/blogaria/185#185\"
  \u003ehttp://www.kubat.nl/pages/blogaria/185#185\u003c/a\u003e.
  Plus, Steve Martin is a champ at sending personal letters - ghe ghe
  - at \u003ca
  href\u003d\"http://www.kubat.nl/pages/blogaria/186#186\"
  \u003ehttp://www.kubat.nl/pages/blogaria/186#186\u003c/a\u003e","links":{"alternate":
  [{"href":"http://www.google.com/buzz/108588487512525984185/L247NmucVAq","type":"text/html"}]},
  "attachments":[{"type":"photo","links":{"preview":[{"href":
  "http://images0-focus-opensocial.googleusercontent.com/gadgets/proxy?container..",
  "type":"image/jpeg"}],"enclosure":[{"href":"http://www.kubat.nl/bld/SushiSaturday/imag0057.jpg",
  "type":"image/jpeg"}]}}]},"source":{"title":"Buzz"},"visibility":{"entries":[{"id":
  "tag:google.com,2010:buzz-group:@me:@public","title":"Public"}]}}]}}
</pre>

Which is of course totally unreadable. Fortunately, there's a
parameter <i>prettyprint=true</i> which makes this a lot better.
Here's an example:

<pre>
curl 'www.googleapis.com/buzz/v1/activities/kkubat/@public?alt=json&max-results=1&prettyprint=true'

{
 "data": {
  "kind": "buzz#activityFeed",
  "links": {
   "next": [
    {
     "href": "https://www.googleapis.com/buzz/v1/activities/108588487512...",
    }
   ],
   "self": [
    {
     "href": "https://www.googleapis.com/buzz/v1/activities/108588487512...",
     "type": "application/json"
    }
   ],
   "hub": [
    {
     "href": "http://pubsubhubbub.appspot.com/"
    }
   ]
  },
  "title": "Google Buzz Public Feed",
  "updated": "2010-06-08T11:09:13.237Z",
  "id": "tag:google.com,2010:buzz-feed:public:posted:108588487512525984...",
  "items": [
   {
    "kind": "buzz#activity",
    "title": "Sushi Saturday - great fun for all, pics at http://www.ku...",
    "published": "2010-06-07T09:35:17.000Z",
    "updated": "2010-06-07T09:35:17.782Z",
    "id": "tag:google.com,2010:buzz:z12lhzwoyvz5z1qfl23rx1vztyrdzdyue",
    "links": {
     "liked": [
      {
       "href": "https://www.googleapis.com/buzz/v1/activities/108588487...",
       "type": "application/json",
       "count": 0
      }
     ],
     "alternate": [
      {
       "href": "http://www.google.com/buzz/108588487512525984185/L247Nm...",
       "type": "text/html"
      }
     ],
     "replies": [
      {
       "href": "https://www.googleapis.com/buzz/v1/activities/108588487...",
       "type": "application/json",
       "count": 0,
       "updated": "2010-06-07T09:35:17.782Z"
      }
     ],
     "self": [
      {
       "href": "https://www.googleapis.com/buzz/v1/activities/108588487...",
       "type": "application/json"
      }
     ]
    },
    "actor": {
     "id": "108588487512525984185",
     "name": "Karel Kubat",
     "profileUrl": "http://www.google.com/profiles/kkubat",
     "thumbnailUrl": "http://www.google.com/s2/photos/public/AIbEiAIAAA...",
    },
    "verbs": [
     "post"
    ],
    "object": {
     "type": "note",
     "content": "Sushi Saturday - great fun for all, pics at \u003ca hr...",
     "links": {
      "alternate": [
       {
        "href": "http://www.google.com/buzz/108588487512525984185/L247N...",
        "type": "text/html"
       }
      ]
     },
     "attachments": [
      {
       "type": "photo",
       "links": {
        "preview": [
         {
          "href": "http://images0-focus-opensocial.googleusercontent.co...",
          "type": "image/jpeg"
         }
        ],
        "enclosure": [
         {
          "href": "http://www.kubat.nl/bld/SushiSaturday/imag0057.jpg",
          "type": "image/jpeg"
         }
        ]
       }
      }
     ]
    },
    "source": {
     "title": "Buzz"
    },
    "visibility": {
     "entries": [
      {
       "id": "tag:google.com,2010:buzz-group:@me:@public",
       "title": "Public"
      }
     ]
    }
   }
  ]
 }
}
</pre>

(Yep, this is readable, but for this page, I shortended the long
  url's with ...)

<p/>
Right, this is better. The return value has the following structure:

<ul>
  <li><i>data</i> is the main hash we're interetested in when we want
  to get at Buzzed items;</li>

  <li><i>items</i> is the next one, which is an array; </li>

  <li>Each array element has an <i>object</i>; </li>

  <li>Each object has <i>content</i> which is the Buzzed text,
  and <i>published</i> is the publishing date;</li>

  <li>Also there is also a hash <i>links</i> with an
  array <i>alternate</i>, pointing to the buzz entries; </li>

  <li>There we are. In this example we won't fetch replies, or
  attachments, or whether someone liked the Buzz or not.</li>

</ul>

Time for some action! Here's a Perl script that fetches the Buzzes and
uses the JSON module to convert the above structure to internal Perly
data. It then prints the Buzz text, publishing date, and URL(s) where
the Buzz can be found. Et voila! A 20-25 liner can do the job. 

<pre>
#!/usr/bin/perl

use strict;
use LWP::UserAgent;
use JSON;

my $public_url = 'http://www.googleapis.com/buzz/v1/activities/'.
  'kkubat/@public?alt=json&max-results=5&prettyprint=true';

# Get the latest 5 buzzes
my $ua = LWP::UserAgent->new();
my $res = $ua->get($public_url);
die("Failed to get buzz: ", $res->status_line(), "\n")
  unless ($res->is_success());

my $buzz;
eval { $buzz = from_json($res->content()); };
die("Bad JSON return: ", $res->content(), "\n") if ($@);

for my $item (@{ $buzz->{data}->{items} }) {
    print("Buzz: ", $item->{object}->{content}, "\n",
	  "Published on: ", $item->{published}, "\n");
    for my $alt (@{ $item->{object}->{links}->{alternate} }) {
	print("URL: ", $alt->{href}, "\n");
    }
    print("\n");
}
</pre>

And of course, here is some sample output. Oh look, it's found a Buzz
about itself, how cute.

<pre>
Buzz: You can read public Buzzes without any hassle - using Perl and
  JSON, what else - read more at
  &lt;a href="http://www.kubat.nl/pages/blogaria/187#187"
     &gt;http://www.kubat.nl/pages/blogaria/187#187&lt;/a&gt;
Published on: 2010-06-08T11:58:10.000Z
URL: http://www.google.com/buzz/108588487512525984185/gkDfAzUGmbz

Buzz: Sushi Saturday - great fun for all, pics at
  &lt;a href="http://www.kubat.nl/pages/blogaria/185#185"
     &gt;http://www.kubat.nl/pages/blogaria/185#185&lt;/a&gt;. Plus, Steve
  Martin is a champ at sending personal letters - ghe ghe - at
  &lt;a href="http://www.kubat.nl/pages/blogaria/186#186"
     &gt;http://www.kubat.nl/pages/blogaria/186#186&lt;/a&gt;
Published on: 2010-06-07T09:35:17.000Z
URL: http://www.google.com/buzz/108588487512525984185/L247NmucVAq

Buzz: Quick note on suppressing auto-submit when someone hits the
  Enter key in an HTML form - at
  &lt;a href="http://www.kubat.nl/pages/blogaria/184#184"
     &gt;http://www.kubat.nl/pages/blogaria/184#184&lt;/a&gt;
Published on: 2010-06-04T12:51:19.000Z
URL: http://www.google.com/buzz/108588487512525984185/eDkoRALSw3K

Buzz: Wormholes on the Dutch highways? I found evidence of that - at
  &lt;a href="http://www.kubat.nl/pages/blogaria/183#183"
     &gt;http://www.kubat.nl/pages/blogaria/183#183&lt;/a&gt;
Published on: 2010-05-31T21:05:02.000Z
URL: http://www.google.com/buzz/108588487512525984185/8Npxwe7EXuf

Buzz: Dutch hosting provider Greenhost has stated not to log user
  traffic&lt;br /&gt;More at
  &lt;a href="http://www.kubat.nl/pages/blogaria/182#182"
     &gt;http://www.kubat.nl/pages/blogaria/182#182&lt;/a&gt;
Published on: 2010-05-25T06:54:03.000Z
URL: http://www.google.com/buzz/108588487512525984185/4ZvjNeWm6m1
</pre>
    
    
 
</description>
   </item>
   <item>
    <title>A Personal Letter from Steve Martin</title>
    <link>http://www.kubat.nl/pages/blogaria/186#186</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This Jenny must've been extatic when she receieved a truly personal
letter from Steve Martin. Now that's funny imo. <i>"Although my
  schedule is very busy, I decided to take the time out to write you a
  personal reply."</i> Priceless.

<p/>
<center>
  <img src="/bld/Steve-Martin-Personal-Letter.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Sushi Saturday</title>
    <link>http://www.kubat.nl/pages/blogaria/185#185</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 
<table>
  <tr>
    <td><center><img src="/bld/SushiSaturday/imag0048.jpg"/></center><br/><center><i>Sticky Sushi rice</i></center></td><td><center><img src="/bld/SushiSaturday/imag0049.jpg"/></center><br/><center><i>Fried seaweed</i></center></td>  </tr>
  <tr><td colspan="2"><hr/></td></tr>
  <tr>
    <td><center><img src="/bld/SushiSaturday/imag0050.jpg"/></center><br/><center><i>Veggies</i></center></td><td><center><img src="/bld/SushiSaturday/imag0051.jpg"/></center><br/><center><i>Some salmon and shrimps, Wasabi and Kikkoman</i></center></td>  </tr>
  <tr><td colspan="2"><hr/></td></tr>
  <tr>
    <td><center><img src="/bld/SushiSaturday/imag0052.jpg"/></center><br/><center><i>Sliced up the veggies</i></center></td><td><center><img src="/bld/SushiSaturday/imag0053.jpg"/></center><br/><center><i>Rolled up</i></center></td>  </tr>
  <tr><td colspan="2"><hr/></td></tr>
  <tr>
    <td><center><img src="/bld/SushiSaturday/imag0054.jpg"/></center><br/><center><i>Chilled for 20 minutes</i></center></td><td><center><img src="/bld/SushiSaturday/imag0055.jpg"/></center><br/><center><i>Finished product</i></center></td>  </tr>
  <tr><td colspan="2"><hr/></td></tr>
  <tr>
    <td><center><img src="/bld/SushiSaturday/imag0056.jpg"/></center><br/><center><i>Looking good</i></center></td><td><center><img src="/bld/SushiSaturday/imag0057.jpg"/></center><br/><center><i>...</i></center></td>  </tr>
  <tr><td colspan="2"><hr/></td></tr>
  <tr>
    <td><center><img src="/bld/SushiSaturday/imag0058.jpg"/></center><br/><center><i>Nothing's wasted</i></center></td><td><center><img src="/bld/SushiSaturday/imag0059.jpg"/></center><br/><center><i>and the dog's happy too</i></center></td>  </tr>
</table>
  
 
</description>
   </item>
   <item>
    <title>Suppressing the Enter key with Javascript</title>
    <link>http://www.kubat.nl/pages/blogaria/184#184</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/watch1.jpg" class="floatright"/>
Memo to myself.

<p/> Here's a simple HTML form that will try to submit when the cursor
is in an input field, and the user hits the Enter key:

<pre>
  &lt;form&gt;
    &lt;iput type="text" name="field"/&gt;
    &lt;input type="submit"/&gt;
  &lt;/form&gt;
</pre>

In order to avoid this:

<ul>

  <li> Create a small Javascript function to catch <i>onkeypress</i>
  events. </li>

  <li> Inside the function, get the code of the key. If the function
  "eats up" the key (as is the case with code 13, Enter), return
  "false". </li>

  <li> Else, return "true" and let the browser handle it. </li>

  <li> Hook up the event handler in the relevant input fields. </li>

</ul>

For example:

<pre>
  &lt;script type="text/javascript"&gt;
    function checkkey(event) {
        var key = event.charCode || event.keyCode;
 	if (key == 13) {
  	    /* Maybe do something interesting here - like refreshing
	     * part of the page with Ajax, or whatever
	     */
	    return false;
	}
        return true;
    }
  &lt;/script&gt;
  .
  .
  .
  &lt;form&gt;
    &lt;input type="text" name="field"
	   onkeypress="return checkkey(event);"/&gt;
    &lt;input type="submit"/&gt;
  &lt;/form&gt;
</pre>
  
    
 
</description>
   </item>
   <item>
    <title>Temporal spacial anomaly on the Dutch highway</title>
    <link>http://www.kubat.nl/pages/blogaria/183#183</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <p/>
<center>
  <img src="/bld/Jam-Signs.jpg"/>
  <br/>
  <i>According to the highway signs, I'm doing fifty...</i>
</center>

<p/>
<center>
  <img src="/bld/Jam-Speedometer.jpg"/>
  <br/>
  <i>But my speedometer is stuck at zero...</i>
</center>

<p/>
Speed equals distance divided by time, and the two observations report
different values. Must be a temporal/spacial anomaly on the Dutch
highway. In the future I'll be on the lookout for wormholes between my car and the Dutch highway signalling system.


 
</description>
   </item>
   <item>
    <title>Greenhost will not log your traffic</title>
    <link>http://www.kubat.nl/pages/blogaria/182#182</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/Greenhost-Logo.png" class="floatright"/>
Dutch hosting provider <a href="http://greenhost.nl">Greenhost</a>
stated on May 20th on
their <a href="http://greenhost.nl/blog/2010/05/greenhost-rekent-af-met-de-bewaarplicht/">blog
(Dutch text)</a> that <b>they will not log their user's traffic</b>.

<p/> A short translation: <i>"Greenhost thinks that traffic logging is
  unnecessary, uncalled for, and unjust. Monitoring e-mail traffic
  makes suspects out of citizens and restricts freedom and
  privacy."</i> As of May 19th, Greenhost has an opt-in policy, where
  custumers can decide for themselves whether their traffic should be
  logged. Sacha van Geffen of Greenhost: <i>"People can choose to be
  treated as a citizen or as a suspect."</i>

<p/> Greenhost states that they are not required to keep traffic logs.
The argument is that if such logs are not necessary for commercial
purposes (i.e., if no logging occurs in the first place) then they
don't need to be kept for any purpose. (I'd love to get legal
confirmation of this from someone.. any experts out there?)

<p/> In any case, kudos to Greenhost!
 
</description>
   </item>
   <item>
    <title>Jarlsberg Webapp Exploits</title>
    <link>http://www.kubat.nl/pages/blogaria/181#181</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/jarlsberg-78.png" class="floatright"/>
The Google Code University released a wonderful exploitable web
application at <a href="http://jarlsberg.appspot.com/"
		  target="_blank">http://jarlsberg.appspot.com/</a>.
It's a must-see for everyone who is interested in attacks on web
applications, and how to defend against them. There are black box or
white box attacks, and examples of cross-site scripting (XSS) and
cross-site request forgery (XSRF), leakage, directory
traversal, and what not. All this is sandboxed so that if every student starts with
a fresh 'hackable' application and proceeds to first compromise it,
then to fix the flaws. Highly recommended!
 
</description>
   </item>
   <item>
    <title>A Thought Experiment</title>
    <link>http://www.kubat.nl/pages/blogaria/180#180</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Bear with me. Just a little thought experiment, a blast from the past
(hey, May 4th is Commemoration Day, so it <b>is</b> fitting in a weird
way).

<p/>
<b>Step 1:</b>
Observe the following video. Go ahead and play it.
<center>
  <object width="480" height="385">
    <param name="movie"
	   value="http://www.youtube.com/v/sSQOeQakExU&hl=en_US&fs=1&"></param>
    <param name="allowFullScreen"
	   value="true"></param>
    <param name="allowscriptaccess"
	   value="always"></param>
    <embed src="http://www.youtube.com/v/sSQOeQakExU&hl=en_US&fs=1&"
	   type="application/x-shockwave-flash" allowscriptaccess="always"
	   allowfullscreen="true" width="480" height="385"></embed>
  </object>
</center>

<p/>
<b>Step 2:</b>
Now instead of that lead singer, in his tight pants, package and all,
imagine Kylie Minogue.

<p/>
<b>Step 3:</b>
Now be honest. What's better, Grand Funk Railroad or Kylie Minogue?
(And please guys control your hormones. I'm doing an *originality*
comparison here. You don't have to imagine Kylie with her shirt off,
just so that it matches the lead singer of GFR.)

<p/>
Yeah, it kinda pays off to be original. Well that's my take at least.
Kylie, you're not even toting a reflecting guitar in your video's of
Locomotion so hey.
 
</description>
   </item>
   <item>
    <title>SafeEdit information updated</title>
    <link>http://www.kubat.nl/pages/blogaria/179#179</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Just updated the information
on <a href="/pages/safeedit">SafeEdit</a>. There's a much better
description now of what SafeEdit can do for you...
 
</description>
   </item>
   <item>
    <title>Microproxy now supports ftp</title>
    <link>http://www.kubat.nl/pages/blogaria/178#178</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/bignose1.jpg" class="floatright"/>
My <a href="/pages/microproxy">microproxy</a> of which
I <a href="/pages/blogaria/165#165">wrote</a>
<a href="/pages/blogaria/166#166">earlier</a>,
now supports the FTP protocol. Stil small and fast, but now defitely
more usable - for those situations where you need to download a file
and the server offers it via ftp. I think that browsing an FTP site
isn't too hot yet but I'll work on it when I find the time.
Downloading works well though. Hope you find it useful!
 
</description>
   </item>
   <item>
    <title>What could get Data angry</title>
    <link>http://www.kubat.nl/pages/blogaria/177#177</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I'm sure that Commander Data ranks pretty high in the top of Persons
Admired by Nerds. Probably because he's the ubergeek, gadgetman and
just simply cool - all in one. And nothing gets him angry. Well..
almost nothing..

<hr/>
<center>
  <img src="/bld/DataBSOD.gif"/>
</center>
 
</description>
   </item>
   <item>
    <title>Lego Mindstorm solving the Rubik Cube</title>
    <link>http://www.kubat.nl/pages/blogaria/176#176</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I came across this today on
<a href="http://hardware.slashdot.org/story/10/04/29/003258/Lego-Robot-Solves-Bigger-and-Harder-Rubiks-Cubes"
target="_blank">Slashdot</a>. A Lego Mindstorm robot that solves
Rubik's Cubes. Way cool!

<hr/>
<object width="640" height="385">
  <param name="movie"
	 value="http://www.youtube.com/v/kWrJdkXp_n4&hl=en_US&fs=1&"></param>
  <param name="allowFullScreen" value="true"></param>
  <param name="allowscriptaccess" value="always"></param>
  <embed src="http://www.youtube.com/v/kWrJdkXp_n4&hl=en_US&fs=1&"
	 type="application/x-shockwave-flash"
	 allowscriptaccess="always"
	 allowfullscreen="true" width="640" height="385">
  </embed>
</object>
 
</description>
   </item>
   <item>
    <title>Crossroads 2.65 is out</title>
    <link>http://www.kubat.nl/pages/blogaria/175#175</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
  <tr>
    <td valign="top">
      Crossroads 2.65 is out, after a long time of no changes or
      releases. This is a bugfix for a fairly rare situation where XR
      would think a back end is down, and would not close the
      associated network socket - which could ultimately lead to file
      descriptor exhaustion. Well, here it is. Crossroads is nicely
      stable nowadays.. good thing.
    </td valign="top">
    <td>
      <img src="/bld/XR265.png"/>
    </td>
  </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Goggomobil in its natural habitat</title>
    <link>http://www.kubat.nl/pages/blogaria/174#174</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Recently I saw a fantastic car - on a normal parking lot, not in a
museum or something. It's an authenthic Goggomobil; an ancient two-stroke
post war German vehicle. I couldn't resist.. here are some shots
(click for original size, the photos are unaltered, except that I've
removed the letters on the registration plate).

<p/> After I shot the pics I got to talk to the owners, an elderly man
and lady. The man was kind of grumpy; I assume that he's hearing
comments about his great car all day and that he's fed up with them.
But the lady was absolutely radiant as I said that this is one of the
finest cars I'd ever seen.

<hr/>
<center>
  <a href="/bld/goggomobil/dsc00109.jpg" target="_blank">
    <img src="/bld/goggomobil/dsc00109-small.jpg"/>
  </a>
</center>

<hr/>
<center>
  <a href="/bld/goggomobil/dsc00110.jpg" target="_blank">
    <img src="/bld/goggomobil/dsc00110-small.jpg"/>
  </a>
</center>

<hr/>
<center>
  <a href="/bld/goggomobil/dsc00111.jpg" target="_blank">
    <img src="/bld/goggomobil/dsc00111-small.jpg"/>
  </a>
</center>

<hr/>
<center>
  <a href="/bld/goggomobil/dsc00112.jpg" target="_blank">
    <img src="/bld/goggomobil/dsc00112-small.jpg"/>
  </a>
</center>

<hr/>
<center>
  <a href="/bld/goggomobil/dsc00113.jpg" target="_blank">
    <img src="/bld/goggomobil/dsc00113-small.jpg"/>
  </a>
</center>

 
</description>
   </item>
   <item>
    <title>Bacon Time</title>
    <link>http://www.kubat.nl/pages/blogaria/173#173</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <img src="/bld/BaconTuxedo.png" alt="Bacon Tuxedo"/>
</center>

This is just too good to let go unnoticed. The only downside is that
it smells like bacon according to the description. If not I'd order
one right away. How cool would that be, walking into the office on
monday morning looking like bacon?

<p/> But wait, there's more! If you want to check out the original
vendor, just go to
<a href="http://www.mcphee.com/shop/pages/Bacon-Tuxedo.html"
target="_blank">McPhee.com</a>. 

<center>
  <img src="/bld/BaconAccessories.png" alt="Bacon Accessories"/>
</center>
 
</description>
   </item>
   <item>
    <title>104 More friends to connect with</title>
    <link>http://www.kubat.nl/pages/blogaria/172#172</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 
I just got a "weekly status report" from
<a href="http://www.plaxo.com/" target="_blank">Plaxo</a>. It seems I
need to connect to 104 more people.

<p/>
<center>
  <img src="/bld/Plaxo.png"/>
</center>

<p/> Coincidentally,
<a href="http://en.wikipedia.org/wiki/World_population"
target="_blank">Wikipedia</a> states that yesterday the world
population was at a staggering 6,813,800.000:

<p/>
<center>
  <img src="/bld/WorldPopulation.png"/>
</center>

<p/> Wow! And I have only 104 to go! Which means that I have already
connected to 6,813,799,896 people! Those guys at Plaxo must have huge
databases and lightning-fast queries to tell whom I'm still missing...
 
</description>
   </item>
   <item>
    <title>Bacteria infested radio reporter</title>
    <link>http://www.kubat.nl/pages/blogaria/171#171</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/happy.jpg" class="floatright"/>
Overheard today on the radio, spoken by an economy reporter: <i>"I am
very septic that the economic crisis will be overcome this
year."</i> (This was actually Dutch: "Ik ben zeer septisch dat...").
I wonder where he got the infection which spread to his bloodstream.
Or did he mean <i>sceptic</i>? Well, I had to laugh a bit...
 
</description>
   </item>
   <item>
    <title>The Kubat STAR</title>
    <link>http://www.kubat.nl/pages/blogaria/170#170</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I got this from my good friend Frank Brokken of the Univ. of
Groningen: <b>my own STandard Instrument ARrival</b> (STAR). Great or
what!

<p/>
<center>
  <img src="/bld/KubatSTAR.png"/>
</center>
 
</description>
   </item>
   <item>
    <title>Homework Essay</title>
    <link>http://www.kubat.nl/pages/blogaria/169#169</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today on the 'net.

<p/>
<i>
You are to assume the role of a Chinese immigrant in 1870 and write a
letter home describing your experiences. Your letter should include
the following: your contribution and experiences in the West.</i>

<p/>
<center>
  <img src="/bld/HomeworkEssay.jpg"/>
</center>

<p/>
LOL!
 
</description>
   </item>
   <item>
    <title>C++ mutexes again</title>
    <link>http://www.kubat.nl/pages/blogaria/168#168</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I <a href="/pages/blogaria/113#113">wrote before</a> about C++,
threads, and mutexes. Well, as things go, ideas evolve and what I'd
thought of as 'done and over with', came back at me.

<p/> The actual reason is that last thursday I was invited at the
State Univ. of Groningen to present a C++ lecture, and I'd picked
daemons, forking, threading, mutexes, and the whole shebang. I
presented the following snippet of how globals could be locked in a
threaded program:

<pre>
// EXAMPLE 1  
// Write something to cout, without other threads interfering in the displayed line.
mutex_lock(&cout);
cout << "Hello World!\n";
mutex_unlock(&cout);

// EXAMPLE 2	
// Function gethostbyname() (DNS resolving) is known to be not thread-safe in many implementations
mutex_lock(gethostbyname);
struct hostent *hostaddr = gethostbyname("www.kubat.nl");
if (hostaddr) {
    .
    . Host successfully resolved
    .
} else {
    .
    . Hostname could not be resolved
    .
}	
mutex_unlock(gethostbyname);	
</pre>

The idea is that <i>mutex_lock()</i> can set a lock on any object, via
its address (a <i>void*</i>). The reverse, <i>mutex_unlock()</i>, releases
the lock. 

<h2>How not to do it</h2>

The work is of course done in the mentioned
functions <i>mutex_lock()</i> and <i>mutex_unlock()</i>. A
controversial implementation is shown below.. read on why it's
controversial, or can you spot it right away?

<pre>
typedef std::map&lt;void *, pthread_mutex_t&gt; LockMap;
static LockMap lockmap;

static void lock_ptr(void *p) {
    if (lockmap.find(p) == lockmap.end() &amp;&amp; pthread_mutex_init(&amp;lockmap[p], 0))
	throw "Failed to initialize mutex";
    if (pthread_mutex_lock(&amp;lockmap[p]))
	throw "Failed to lock mutex";
}
static void unlock_ptr(void *p) {
    if (pthread_mutex_unlock(&amp;lockmap[p]))
	throw "Failed to unlock mutex";
}

void mutex_lock(void *p) {
    lock_ptr(&amp;lockmap);
    lock_ptr(p);
    unlock_ptr(&amp;lockmap);
}
void mutex_unlock(void *p) {
    unlock_ptr(p);
}
</pre>

Internally, the functions use a map to find the right
mutexes for each <i>void*</i> that's being handled. When locking
something, function <i>mutex_lock()</i> first locks the entire map of
locks, and then calls <i>lock_ptr(p)</i> to set a lock for that
specific object. However, when unlocking, <i>mutex_unlock()</i>
does <b>not</b> lock the entire map - the idea being that the map
isn't being expanded, just read.

<h2>What's the problem?</h2>

<p/> "Aha," said the audience (specifically Thomas ten C., thanks for
all the comments!), "there's a potential problem there!" The
implementation of the Standard Template Library (STL) isn't guaranteed
to be thread-safe; e.g., consider the following:

<ul>
  
  <li> A thread is unlocking an object. It is at the
  statement <i>lockmap[p]</i> in line 12. </li>

  <li> Another thread is at that time locking, and is at line 5,
  at <i>lockmap.find(p) == lockmap.end()</i>.</li>

  <li> But, if the STL implementation for <i>std::map</i> isn't
  thread-safe, then these two threads might mess up the underlying map
  beyond imagination...</li>

</ul>

<p/> I had assumed that <i>reading</i> the map wouldn't modify its
layout, so that entire map locking would be only necesary during
the <i>writing</i> phase, i.e., the locking of a particular object.
Not necessarily true. "Assume nothing", I should've known... Thomas
commented in a mail:

<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top"><a href="http://msdn.microsoft.com/en-us/library/c9ceah3b(VS.80).aspx"
target="_blank">Microsoft</a> writes: "A single object is thread safe
for reading from multiple threads. [...] If a single object is being
written to by one thread, then all reads and writes to that object on
the same or other threads must be protected."</td></tr></table>

<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">The SGI
implementation, and the GNU implementation which uses this, is
thread-safe when reading: "The
<a href="http://www.sgi.com/tech/stl/thread_safety.html"
target="_blank">SGI implementation</a> of STL is thread-safe only in
the sense that simultaneous accesses to distinct containers are safe,
and simultaneous read accesses to to shared containers are safe."
<a href="http://gcc.gnu.org/onlinedocs/libstdc++/manual/using_concurrency.html"
target="_blank">Gnu</a> uses the same definition: "We currently use
the SGI STL definition of thread safety."</td></tr></table>

<h2>Now what</h2>

Right. So where does that leave us? There could be several approaches
to avoid errors that involve a combination of STL containers and mutex
locking. One is, to apply a much wider lock scope before
handling <i>std::map</i>. Or, to also lock the entire map during the
unlocking phase. Hmmm... Another one is, not to use <i>std::map</i>,
but to <b>control the implementation</b> where <i>std::map</i> isn't
clearly defined. That means implementing the equivalent of a map in
code which is guaranteed <b>not</b> to reshuffle anything in read/only
mode. And that code is exactly what's shown below, up to the global
functions <i>mutex_lock()</i> and <i>mutex_unlock()</i>. The below
sections show and explain what's going on.

<p/> <b>If you are interested in a source file having all this code
inside: you can <a href="/bld/mutex.cc">grab it here</a>.</b> All classes
and members are contained in one file - including a <i>main()</i>
function to test it all. If you want to use it, then feel free to
split it up and customize it however you like.

<h3>Basic Mutex</h3>

A basic mutex is implemented in the class <i>Mutex</i> (how fitting).
All it does, is initialize a mutex if necessary, lock it, or unlock
it. For reasons of brevity, strings are thrown when errors occur.

<pre>
class Mutex {
public:
    Mutex(): _initialized(false) 	{ }
    void lock();
    void unlock();
private:
    pthread_mutex_t _mutex;
    bool _initialized;
};

void Mutex::lock() {
    if (!_initialized) {
	_initialized = true;
	if (pthread_mutex_init(&_mutex, 0))
	    throw "Failed to initialize mutex";
    }
    if (pthread_mutex_lock(&_mutex))
	throw "Failed to lock mutex";
}    

void Mutex::unlock() {
    if (pthread_mutex_unlock(&_mutex))
	throw "Failed to unlock mutex";
}
</pre>

<h3>Mutex Nodes</h3>

Internally, the mutexes will be stored as a tree - having leaves. The next
level is therefore a node, which has a mutex, a left branch, and a right branch:

<pre>
class MutexNode {
public:
    MutexNode(void *o);
    ~MutexNode();
    
    void obj(void *o)			{ _obj = o; }
    void *obj() const  			{ return _obj; }

    void left(MutexNode *l)		{ _left = l; }
    MutexNode *left() const   		{ return _left; }

    void right(MutexNode *l)		{ _right = l; }
    MutexNode *right() const   		{ return _right; }

    void lock()				{ _mutex.lock(); }
    void unlock()			{ _mutex.unlock(); }
    
private:
    Mutex _mutex;
    void *_obj;
    MutexNode *_left, *_right;
};

MutexNode::MutexNode(void *o): _mutex(), _obj(o) {
    _left = _right = 0;
}

MutexNode::~MutexNode() {
    delete _left;
    delete _right;
}
</pre>  

<h3>The Mutex Tree</h3>

The nodes are maintained in a tree - here is the typical recursive
descent algorithm, and so on. Note also the
method <i>MutexTree::lock()</i> which locks the entire tree before
applying a lock to a singular node.

<pre>   
class MutexTree {
public:
    MutexTree();
    ~MutexTree();
    
    void lock(void *o);
    void unlock(void *o);
    
private:
    void locktree()		{ _treelock.lock(); };
    void unlocktree()		{ _treelock.unlock(); }
    MutexNode *nodelock(void *o, MutexNode *start);
    void nodeunlock(void *o, MutexNode *start);
    
    MutexNode *_root;
    Mutex _treelock;
};

MutexTree::MutexTree(): _treelock() {
    _root = 0;
}

MutexTree::~MutexTree() {
    delete _root;
}

void MutexTree::lock(void *o) {
    locktree();
    _root = nodelock(o, _root);
    unlocktree();
}

void MutexTree::unlock(void *o) {
    nodeunlock(o, _root);
}

MutexNode *MutexTree::nodelock(void *o, MutexNode *start) {
    if (!start) {
	start = new MutexNode(o);
	start->lock();
    } else if (start->obj() == o)
	start->lock();
    else if (start->obj() < o)
	start->left(nodelock(o, start->left()));
    else
	start->right(nodelock(o, start->right()));
    
    return start;
}

void MutexTree::nodeunlock(void *o, MutexNode *start) {
    if (!start)
	return;
    
    if (start->obj() == o)
	start->unlock();
    else if (start->obj() < o)
	nodeunlock(o, start->left());
    else
	nodeunlock(o, start->right());
}
</pre>

<h3>Translating to mutex_lock() and mutex_unlock()</h3>

The class <i>MutexTree</i> is sufficient to implement the two
classless functions shown at the top of this post. All we need is one
static <i>MutexTree</i> to operate on:

<pre>
static MutexTree mt;

void mutex_lock(void *obj) {
    mt.lock(obj);
}

void mutex_unlock(void *obj) {
    mt.unlock(obj);
}
</pre>

<h3>Test Harnass</h3>

Plus of course, here's the test...

<pre>
void *test(void *data) {
    for (int i = 1; i <= 10; i++) {
	if (i & 1) {
	    mutex_lock(&cout);    
	    cout << pthread_self() << " testing cout, loop " << i << '\n';
	    mutex_unlock(&cout);
	} else {
	    mutex_lock(&cerr);
	    cerr << pthread_self() << " testing cerr, loop " << i << '\n';
	    mutex_unlock(&cerr);
	}
    }
    return 0;
}

int main() {
    try {
	pthread_t th, threads[10];
	for (unsigned i = 0; i < sizeof(threads) / sizeof(pthread_t); i++) {
	    pthread_create(&th, 0, test, 0);
	    threads[i] = th;
	}
	for (unsigned i = 0; i < sizeof(threads) / sizeof(pthread_t); i++)
	    pthread_join(threads[i], 0);
	cout << "Done!\n";
	return 0;
    } catch (char const *s) {
	cerr << s << "\n";
	return 1;
    }
}  
</pre>

<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top"><b>Update:</b> I've modified the above version for faster
   access - which can be useful in programs that use up a lot of
   mutexes. The modified version has a hash-table, which indexes
   trees. The first lookup of a mutex given a <i>void*</i> is
   therefore much faster. <a href='mailto:karel@kubat.nl'>Drop me a
   note</a> if you are interested.

   <p/> The hash-table version wins performance-wise in a worst-case
   scenario where loads of mutexes are being used, all relating to
   linearly situated objects. E.g, consider:

   <pre>
     int obj[5000];
     for (int i = 0; i &lt; 5000; i++)
         mutex_lock(&obj[i]);</pre>

   This is the worst case, in the sense that each consecutive object
   to lock is (pointer-wise) 'larger' than the previous. The binary
   tree of MutexTree will degenerate into a list. That's where the
   hash table is beneficial.

   <p/> However, most programs (a) won't have that many mutexes, and
   (b) won't suffer from such linearity. I think therefore that in
   most situations the binary tree approach will do quite nicely.</td></tr></table>
 
</description>
   </item>
   <item>
    <title>Weird Eyechart</title>
    <link>http://www.kubat.nl/pages/blogaria/167#167</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This must be taken from a textbook of one of the
extremely-densely-wired countries, where kids learn to say "OMG, bio brb"
before anything else... Also be sure to check line 5, "pwn3d" spelled
in real leet-speak ;-) <br/>
(Originally seen on <a href="http://www.failblog.org"
target="_blank">Failblog.org</a>) 

<p/>

<center>
<img src="/bld/EyechartFail.jpeg"/>
</center>
 
</description>
   </item>
   <item>
    <title>Microproxy 1.01</title>
    <link>http://www.kubat.nl/pages/blogaria/166#166</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I <a href="/pages/blogaria/165#165">wrote before</a> about my teeny
tiny proxy <a href="/pages/microproxy">Microproxy</a>. Well, version
1.01 is out - it helps in situations where your DNS queries over TCP
are more reliable than over UDP. In that case, just add flag <i>-t</i>
to the invocation...

 
</description>
   </item>
   <item>
    <title>Microproxy</title>
    <link>http://www.kubat.nl/pages/blogaria/165#165</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/scratch.png" class="floatleft"/>
I wrote <a href="/pages/blogaria/157#157">before</a> how DNS lookups
after sleep/wake cycles messed up my locally running proxies. I'd
tried <a href="/pages/blogaria/108#108">Squid</a>, I'd tried Perl's
<a href="/pages/blogaria/155#155">HTTP::Proxy</a> module - but all suffered
from this effect. As announced, there would be some tinkering, but the
DNS problem was solvable. Well, tinkering time's over and here's the result.

<p/> I have scratched my own itch and wrote my own tiny little proxy
in C++. It works like a charm for what I want. It's small, it's got a
minimal footprint, it's fast. 
If you're interested - it's right at this site and it's
called <a href="/pages/microproxy">microproxy</a>.
 
</description>
   </item>
   <item>
    <title>Sven Kramer and the wrong lane</title>
    <link>http://www.kubat.nl/pages/blogaria/164#164</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The poor guy. He was right on track for the 10km Gold Medal in
speedskating during the recent Olympic Games. But his coach sent him
into the wrong lane and he got disqualified.

<p/> Didn't take long 'till the funnies started coming in..

<center>
  <hr/>
  <img src="/bld/WelkeBaan.png"/>

  <hr/>
  <img src="/bld/Monsterboard.png"/>

  <hr/>
  <img src="/bld/Ticket.png"/>

</center>  
 
</description>
   </item>
   <item>
    <title>Endearing Babe Magnet</title>
    <link>http://www.kubat.nl/pages/blogaria/163#163</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Suddenly, at middle age, the <b>Perfect Recipy to be a Babe Magnet</b>
stikes home.

</p> Here's how you do it. Go skiing without the wife (or, if
appropriate, wihout husband, whatever your situation may warrant) but
with the kids (in my case, two sons, aged 13 and 14). Walk around with
your two kids, holding a snowboard, and if appropriate: hit the snow
slopes, with the snowboard strapped under your feet.

<p/> This appears to have an irresistible attaction to the opposite
sex (in my case, females). From young waitresses, thru middle-aged
mums, to elderly grannies: they'll all chat you up - and they'll
expect you to chat back. What's even better: even the silent ones
aren't surprised when you chat them up.

<p/> This is a free tip. As with all that's free, there's also no warranty...
 
</description>
   </item>
   <item>
    <title>Speed of light measured using chocolate and a microwave</title>
    <link>http://www.kubat.nl/pages/blogaria/162#162</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This is too good to pass up. If you have some spare chocolate and a
microwave, you can measure the speed of light - writes 
<a href="http://www.wired.com/geekdad/2010/02/leftover-valentines-chocolate-use-it-to-measure-the-speed-of-light/"
target="_blank">Kathy Celeri on wired.com</a>. Just brilliant! In a
simple home-grown experiment she comes up with 2.94e8 m/s - which is
darn close to the speed of light in vacuum, 2.99e8. Kudos!
 
</description>
   </item>
   <item>
    <title>Never again expires after 65 years</title>
    <link>http://www.kubat.nl/pages/blogaria/161#161</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/angry.png" class="floatleft"/>
The Dutch government has recently forced the following security
measure upon us poor Dutchies: <i>In all new passports a fingerprint will
be included as a biometric identification measure, and furthermore,
all fingerprints will be centrally stored in a governmental
database.</i> 

<p/> After some initial protest - mainly from the leftist parliament
members, but hey, who listens to those guys - the measure was
motivated by stating that the European Union requires this. Basta.
However, the truth is somewhat different: The EU does require a
biometric parameter in passports (as counterfeit measure), but <b>does
not</b> require central storage of such ID's. And there's the catch.
Although the Dutch government is complying with EU regulations, they're
going way further than that. And they're walking a dangerous path.

<p/> Only 65 years ago, the Dutch people said "Never Again" to the
antrocities of the second world war. "Never Again" to publicly marking
people with identifications, such as of course the Jewish star that
had to be sewn on coats and be visible at all times. History knows
where that led to - readily available identification is oh-so-handy,
and not only for benefical purposes..

<p/> The Dutch civil rights organisation "Het Niewe Rijk" (The New
Empire) got into action and distributed approx. 60.000 flyers,
inviting citizens to come to their town halls to have their social
security number tatooed on their wrist. (For example, read "The Press",
<a href="http://www.depers.nl/binnenland/355671/Gratis-tatoeage-met-burgerservicenummer.html"
target="_blank">depers.nl</a>.) The proponents of the governamental
fingerprinting measure of course yelled "shame on you", and called
this a disgusting protest.

<p/> But actually, Het Nieuwe Rijk is totally right. When all
fingerprints are centrally stored, then all that officials have to do,
is to carry around a portable fingerprint scanner with a wireless
connection. Within seconds they'll not only know whether you're Jew,
Catholic, Muslim or whatever, but they'll also know where and how you
are insured, on what no-fly list you are present, where you live, what
car you drive and how environment-friendly it is, and so on. In a
sense, this fingerprint storage goes way beyond the Jewish star of
WW2: we now carry countless identification stars with us. And we can't
take them off - fingerprints are forever. And arguments that this
government just wants "the best" for us and can be trusted, are
absolutely invalid: even if we do trust this government, why are we
forced to state that we'll also trust the next one, and the next, and
so on?

<p/> We're tagged. We're waiting to be bagged.

<hr/>
<center>
  <img src="/bld/Yellowstar.jpeg"/> <br/>
  <b>"Never again" has lasted 65 years in the Netherlands.</b>
</center>

 
</description>
   </item>
   <item>
    <title>encfs on the Mac</title>
    <link>http://www.kubat.nl/pages/blogaria/160#160</link>
    <pubDate>Fri, 29 Mar 13 09:31:36 +0100</pubDate>
    <description>
 <img src="/bld/k/happy.jpg" class="floatright"/>
I recently read a nice article on FileFault vs. EncFS on
<a href="http://techieblurbs.blogspot.com/2010/02/howto-replace-filevault-with-encfs.html"
target="_blank">techieblurbs.blogspot.com</a>, and I decided to try it
out - with success. The topic really is about one of my own use cases
that I'd been thinking about. Here's what I found...

<p/> In order to protect customers' data, I used to create encrypted
disk images using my Mac's Disk Tool. This works really well: you
assign a file to serve as image, then you open the encrypted image and
while mounting it, MacOSX asks you for a pass phrase. Once mounted,
the separate files are accessible. The only drawback is that backing
it up is a pain:

<ul>

  <li> Either I backed up the encrypted entire image file, so that
  the data would remain encrypted on the back up media. But this means
  that incremental back ups take very long. Every small change within
  such a filesystem leads to changes in the image, and hence the image
  file is eligible for back up. </li>

  <li> Or, I backed up separate files from the image while it was
  mounted - which makes incremental back ups fast, but leaves the
  separate files unencrypted on the media. This of course creates a
  security hole that I don't want. </li>

</ul>

Enter encfs. This is a FUSE filesystem: a file system in "userland"
that maps typical file-related system calls (open(), close(),
opendir() and so on) to custom handlers. In the case of encfs, the
handlers make sure that file by file, all passing information is
encrypted or decrypted on the fly. This means that each file appears
in its unecrypted form to any software, while it is actually stored in
encrypted form on the disk.

<p/> Here's how to get encfs for the Mac: Make sure that you have the
<a href="http://www.macports.org/" target="_blank">MacPorts</a>
package, and then simply type (as root):

<pre>port -v install encfs</pre>

<p/> And here's how to use encfs.

<ul>

  <li> As any non-root user, create two directories to (a) hold
  encrypted files, (b) be the non-encrypted representation. This is
  required only once. For example:
<pre>
# The username is assumed to be "myname" in this example
# The directory pair is PlainDocs and .EncDocs
mkdir /Users/myname/PlainDocs /users/myname/.EncDocs
</pre></li>

  <li> Next, assign the mapping between the directories using the
      command <i>encfs</i>. This is very similar to mounting:
<pre>
# Adjust the directory names as required on your own system
encfs /Users/myname/PlainDocs /users/myname/.EncDocs
</pre></li>

  During this step, encfs will ask for a passphrase. Obviously, choose
  something you can remember - but something not obvious ;-) The first
  time this is done, encfs prompts for a few file system related
  settings - leave them to their defaults, or pick your own.

  <li> Make sure that <i>/Users/myname/.EncDocs</i> is
  included in your back up scheme, and <i>/Users/myname/PlainDocs</i>
  is excluded. You want to back up the encrypted files, but not the
  plain-text ones. </li>

  <li> After modifying or reading files
  in <i>/Users/myname/PlainDocs</i>, unmap the encrypted filesystem,
  by entering as root:
<pre>
# Replace /Users/myname/PlainDocs with whatever is applicable
# in your situation
umount /Users/myname/PlainDocs
</pre></li>

</ul>

This works really like a charm and does the job. Just the last step is
kind of bothersome: what if you forget to unmap the encrypted
filesystem, and your laptop gets stolen whilst in sleepmode or at the
login screen? Fortunately, MacOSX has "hooks" that are run upon events
such as: putting the laptop into sleepmode, or logging out. So, the
last step of unmapping the encrypted filesystem can be automated as
follows:

<ul>

  <li> As root, create a script <i>/var/root/bin/umount-encfs</i> with
  the following contents (I put this file under root's home directory
  so root only can see it, but you can use any path you like, just
  make sure it has root-only privileges):
<pre>
#!/bin/sh

# /Users/myname/PlainDocs is the mapped directory,
# adjust for your own purposes
pids=`lsof /Users/myname/PlainDocs | awk '{if (NR > 1) print $2}'`
if [ -n "$pids" ] ; then
    kill $pids
    kill -1 $pids
fi
umount /Users/myname/PlainDocs
</pre>

  The purpose of this file is to list all programs that use files in
  the plain-documents directory, and to stop those programs. Then the
  directory is unmounted. </li>

  <li> Make this script executable, using:
    <pre>chmod +x /var/root/bin/umount-encfs</pre></li>
    
  <li> Make sure that the script is called when the laptop goes into
  sleepmode. Run as root:
<pre>
# umount-encfs should be run when logging out  
defaults write com.apple.loginwindow LogoutHook \
  /var/root/bin/umount-encfs
 
# umount-encfs should be run when entering sleep mode
defaults write com.apple.loginwindow SleepHook \
  /var/root/bin/umount-encfs
</pre></li>

</ul>

Presto. Done.

<hr/>
<b>Update:</b> The stock encfs program doesn't handle relative paths
too well. The following illustrates this:

<pre>
  # This works
  encfs /Users/myname/PlainDocs /Users/myname/.EncDocs
</pre>

but the following won't:

<pre>
  # This doesn't work.. sigh
  cd /Users/myname
  encfs PlainDocs .EncDocs
</pre>

So either you have to type absolute file names, or you can use the
following tiny Perl script. I've saved this in my <i>$HOME/bin</i>
directory as <i>encfs</i>, and my $PATH makes sure that it is found
before before <i>/opt/local/bin/encfs</i>. So when I run the command
encfs, my script is actually run - and the script inspects arguments
and converts to absolute file names, and then runs the true encfs
program.

<pre>
<span class="comment-delimiter">#</span><span class="comment">!/usr/bin/perl
</span>
<span class="keyword">use</span> <span class="function-name">strict</span>;
<span class="keyword">use</span> <span class="function-name">Cwd</span> <span class="string">'abs_path'</span>;

<span class="keyword">my</span> <span class="variable-name">$encfs</span> = <span class="string">'/opt/local/bin/encfs'</span>;

<span class="comment-delimiter"># </span><span class="comment">Convert all args to absolute paths.
</span><span class="keyword">my</span> <span class="cperl-array">@args</span> = (<span class="variable-name">$encfs</span>);
<span class="keyword">for</span> <span class="keyword">my</span> <span class="variable-name">$a</span> (<span class="cperl-array">@ARGV</span>) {
    <span class="keyword">if</span> (<span class="function-name">-f</span> <span class="variable-name">$a</span>) {
        <span class="cperl-nonoverridable">push</span>(<span class="cperl-array">@args</span>, abs_path(<span class="variable-name">$a</span>));
    } <span class="keyword">elsif</span> (<span class="function-name">-d</span> <span class="variable-name">$a</span>) {
        <span class="cperl-nonoverridable">push</span>(<span class="cperl-array">@args</span>, abs_path(<span class="variable-name">$a</span>) . <span class="string">'/'</span>);
    } <span class="keyword">else</span> {
        <span class="cperl-nonoverridable">push</span>(<span class="cperl-array">@args</span>, <span class="variable-name">$a</span>);
    }
}

<span class="comment-delimiter"># </span><span class="comment">Exec true encfs
</span><span class="cperl-nonoverridable">print</span> (<span class="string">"Running: </span><span class="cperl-array">@args</span><span class="string">\n"</span>);
<span class="keyword">exec</span>( {<span class="variable-name">$encfs</span>} <span class="cperl-array">@args</span> );
<span class="keyword">die</span>(<span class="string">"Failed to exec $encfs: $!\n"</span>);
</pre>

<p/>
<img src="/bld/warning.png" class="floatleft"> Update: if you're
interested in using encfs, read
also <a href="/pages/blogaria/292">encfs revisited</a>. In that blog
post I'm describing the newer and better and hotter encfs helper
script ;-)
 
</description>
   </item>
   <item>
    <title>Hyves.nl and sexual predators</title>
    <link>http://www.kubat.nl/pages/blogaria/159#159</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The mainly Dutch-oriented social networking site Hyves.nl (still
popular - despite Facebook, Orkut, Twitter, Google's Buzz and many
others) recently took part in a "scientific project". This involved
data mining: The profiles of known pedophiles were investigated, and
the number of minor-age friends on their profiles was counted. This
number was compared with the profile pages of other Hyves users. The
project was a cooperation with the Dutch police. They had two
startling results to show:

<ul>

  <li> In the age group between say 30 and 40 years, there was a
  significant correlation between known pedophilic tendencies and
  the number of minor-age friends. </li>

  <li> Above that, say 45 years and up, the correlation disappeared -
  this was attributed to people stating their kids or grandkids as
  friends, thereby driving up the average number of minor-age
  friends. </li>

</ul>

The obvious conclusion: "Data mining of such sets makes sense. Given
more research and obviously taking the right precautions, such analyses
may in the future become valuable assets in stopping dangerous sexual
predators."

<p/> Are these guys totally mental?

<p/> Don't get me wrong - I have kids myself, and just thinking about
them being victimized is one of the worst things imaginable. But
please take a step back:

<p/> 
<b>Customer:</b> <i>"I'm really really fond of hamburgers. Can you devise a way
to get me really great meat on my burgers?"</i> <br/>

<b>Statistician:</b> Goes off to do his magic, spends the budget required for
this task, requests some more, then comes back with preliminary
results: <i>"We have analyzed a significant sample of cows, which, as we
know, often provide good burger meat. We have found that
there is a significant correlation with the fact that these cows are
mammals. We feel that further analysis is required: given more
research and obviously taking the right precautions, such analyses may
in the future become valuable assets in determining whether mammals
are a good source of burger meat."</i>

<p/> So basically the guys have found that known pedophilic predators
on Hyves have significantly more minor-age friends - given the right
age groups and so on. Yeah, a cow's a mammal. But what's the chance
that any given mammal is a cow? What's the chance that some Hyves user
with more than X minor-age friends is a pedophile, or will ever become
one? This research no-where states how many Hyves
users with minor-age friends actually are pedophilic sexual predators. The
research has no predictive value whatsoever. Bleeding waste of my tax
money, if you ask me.

<p/> Bayesian stats, biting 'em again. See
also <a href="/pages/blogaria/110#110">prohibiting photography</a> and
why it won't stop terrorism. See also the dangers of 
<a href="/pages/blogaria/55#55">evidence based on fingerprints</a>
when statistics are not applied correctly. They've got
it the the wrong way 'round. Give it up, spend the money on something
useful. Or give the money to someone who can...

<p/> Or, if I'm totally off-base here, and the research was actually
well planned and executed, taking all of the above points into
consideration - then please enlighten me.
 
</description>
   </item>
   <item>
    <title>Funny textbook</title>
    <link>http://www.kubat.nl/pages/blogaria/158#158</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today on
<a href="http://failblog.org/2010/02/09/tell-me-what-you-see/"
   target="_blank">Failblog</a>:

<center>
  <img src="/bld/EyechartFail.jpeg"/>
</center>

<p/> Seems they're teaching kids Internet acronyms at a very early
stage nowadays. LOLZ! There's even <i>pwn3d</i> if you look closely.

 
</description>
   </item>
   <item>
    <title>DNS failing after sleep wake cycle</title>
    <link>http://www.kubat.nl/pages/blogaria/157#157</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 As I wrote <a href="/pages/blogaria/155#155">before</a>, I'd been
using a simple straight-thru proxy based on Perl's HTTP::Proxy on my
laptop. However, just as is the case with Squid, after a sleep/wake
cycle, the proxy would just barf and not come back to life. At such
times I would have to manually kill the proxy process and restart it -
after which it would magically work again.

</p> Annoying? Highly so. Impossible to solve? No way. If there's
tinkering to be done, then tinkering it will be. I traced the problem
to a failure of the DNS subsystem. After a sleep/wake cycle of the
laptop, the C function <i>gethostbyname()</i> would simply return NULL
and would not come back to life. Obviously, any proxy process that
relies on domain name services, falls dead right there.

<p/> Oh the joy of having code to work on where you can tinker around
and fix stuff. Oh the even bigger joy when it's your own code. Well,
to summarize: I started writing my own simple straight-thru proxy
where I know what's happening and why, and where I can freely tinker
around. I'll post it on this site once I'm comfortable with it. In the
mean time: here's a preview of how the DNS issue can be fixed.

<p/> Below is a C++ function <i>dnsresolve()</i> which takes one argument:
a hostname. Its address is returned as an <i>in_addr_t</i> struct. The
function basically just wraps <i>gethostbyname()</i> but additionally
it does two things:

<ul>

  <li> DNS entries are cached. Typically a browser will request a page
  from <i>http://somesite/index.html</i>, then the index page will
  lead to a multitude of requests
  like <i>http://somesite/stylesheet.css</i>, <i>http://somesite/logo.png</i>,
  and what not. So caching DNS entries makes sense: subsequent
  requests from a site don't have to be resolved. </li>

  <li> When a DNS lookup fails, then the resolver
  function <i>res_init()</i> is called. There's the missing part! This
  was what I was looking for all along in Squid or HTTP::Proxy...
  Having this in the code means that after a sleep/wake cycle, the
  first DNS lookup will fail but that this lookup will
  invoke <i>res_init()</i>. If the network is up and running by that time,
  then next lookups will succeed by using the new resolver
  environment.

    From the manpage: <i>The res_init() routine reads the
      configuration file (if any; see resolver(5)) to get the default
      domain name, search list and the Internet address of the local
      name server(s).</i> Brilliant. That's exactly what I needed, and
    now I know where to get it. </li>
</ul>

Incase you're interested, here's the code for my
wrapper <i>dnsresolve()</i>. I'm not adding all header files etc. to
keep the listing somewhat readable. It'll be in my upcoming microproxy
for sure, so stay tuned if you're interested ;-)

<pre>
<span class="preprocessor">#include</span> <span class="string">"main"</span>

<span class="comment-delimiter">// </span><span class="comment">Single DNS entry in the cache: address and the time it was resolved
</span><span class="keyword">struct</span> <span class="type">DnsEntry</span> {
    <span class="type">in_addr_t</span> <span class="variable-name">dnsresult</span>;
    <span class="type">int</span> <span class="variable-name">lookuptime</span>;
};

<span class="comment-delimiter">// </span><span class="comment">Typedefs: map of entries, iterator
</span><span class="keyword">typedef</span> <span class="constant">std</span>::<span class="type">map</span>&lt;<span class="type">string</span>, <span class="type">DnsEntry</span>&gt; <span class="type">DnsMap</span>;
<span class="keyword">typedef</span> <span class="constant">DnsMap</span>::<span class="type">iterator</span> <span class="type">DnsMapIterator</span>;

<span class="comment-delimiter">// </span><span class="comment">Cache of entries
</span><span class="keyword">static</span> <span class="type">DnsMap</span> <span class="variable-name">dnsmap</span>;

<span class="comment-delimiter">// </span><span class="comment">dnsresolve("hostname") returns the resolved name as an in_addr_t type
</span><span class="comment-delimiter">// </span><span class="comment">and caches the result. The cache expiry is 'nsexpiry' seconds.
</span><span class="comment-delimiter">// </span><span class="comment">Upon failure a string exception is thrown.
</span><span class="type">in_addr_t</span> <span class="function-name">dnsresolve</span>(string <span class="keyword">const</span> &amp;<span class="variable-name">host</span>) {

    <span class="comment-delimiter">// </span><span class="comment">See if we have the record stored yet and if it's still recent.
</span>    <span class="type">DnsMapIterator</span> <span class="variable-name">it</span> = dnsmap.find(host);
    <span class="keyword">if</span> (it != dnsmap.end()) {
        <span class="type">DnsEntry</span> <span class="variable-name">entry</span> = dnsmap[host];
        <span class="keyword">if</span> (entry.lookuptime &gt;= time(0) - nsexpiry) {
            MSG(4, (msg &lt;&lt; <span class="string">"DNS cache for "</span> &lt;&lt; host &lt;&lt; <span class="string">" still valid"</span>));
            <span class="keyword">return</span> entry.dnsresult;
        }
    }

    <span class="comment-delimiter">// </span><span class="comment">Not found or expired. Look up.
</span>    mutex_lock((<span class="type">void</span>*)gethostbyname);
    <span class="keyword">struct</span> <span class="type">hostent</span> *<span class="variable-name">hostaddr</span> = gethostbyname(host.c_str());
    mutex_unlock((<span class="type">void</span>*)gethostbyname);

    <span class="comment-delimiter">// </span><span class="comment">If lookup is succesful: enter in cache. Else throw exception and reset
</span>    <span class="comment-delimiter">// </span><span class="comment">the resolver lib. A next time might be successful - e.g. after a
</span>    <span class="comment-delimiter">// </span><span class="comment">laptop wakeup on a new network (then the daemon must be kicked into
</span>    <span class="comment-delimiter">// </span><span class="comment">life).
</span>    <span class="keyword">if</span> (hostaddr) {     
        <span class="type">DnsEntry</span> <span class="variable-name">entry</span>;
        MSG(4, (msg &lt;&lt; <span class="string">"DNS queried succesfully for "</span> &lt;&lt; host));
        memcpy(&amp;entry.dnsresult, hostaddr-&gt;h_addr_list[0], <span class="keyword">sizeof</span>(in_addr_t));
        entry.lookuptime = time(0);
        dnsmap[host] = entry;
        <span class="keyword">return</span> entry.dnsresult;
    } <span class="keyword">else</span> {
        <span class="type">ostringstream</span> <span class="variable-name">o</span>;
        o &lt;&lt; <span class="string">"Failed to resolve downstream host "</span> &lt;&lt; host
          &lt;&lt; <span class="string">": "</span> &lt;&lt; strerror(errno);
        res_init();
        <span class="keyword">throw</span> <span class="type">o</span>.str();
    }
}
</pre>

<b>Update:</b> The final version will also lock the static cache
map <i>dnsmap</i>. Not yet included in this code (though mutex-locking
around <i>gethostbyname()</i> is already in...)
 
</description>
   </item>
   <item>
    <title>Blast from the past</title>
    <link>http://www.kubat.nl/pages/blogaria/156#156</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I just recently came across an ancient article in
<a href="http://www.linuxjournal.com"
target="_blank">Linuxjournal</a>. It must be one of the first
articles ever there, dated November 1st, 1997. The
<a href="http://www.linuxjournal.com/article/2089"
target="_blank">article</a> is about
<a href="http://sourceforge.net/projects/yodl/"
target="_blank">Yodl</a>, a document preprocessor. There was also a
really ancient picture there, from the old days before digital
camera's - I have no idea really how I got that photo into binary
format. Ah yeah, the good old days. I drove a red Volvo Amazon, and had a
Blues Brothers t-shirt ;-)

<p/>
<center>
  <img src="/bld/Karel-BBshirt.png"/>
</center>
 
</description>
   </item>
   <item>
    <title>Simple and straight Perl HTTP::Proxy</title>
    <link>http://www.kubat.nl/pages/blogaria/155#155</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/happy.jpg" class="floatright"/>
I wrote earlier about my pet
project <a href="/pages/blogaria/124#124">Crossroads</a>, a software
load balancer. I actually use it daily on my laptop - the main purpose
being that I don't have to reconfigure my browser to different proxies
in different environments. Basically, my setup is:

<ul>

  <li> I run Crossroads on my local system on port 8000. My Firefox is
  configured to use localhost:8000 as its proxy to talk to the outside
  world. </li>

  <li> Crossroads knows about a number of back ends: e.g., at a
  customers' location there's a proxy that Crossroads can dispatch to,
  at the office there's a Squid proxy to talk to and so on. </li>

  <li> When I'm at home, without an outgoing proxy, there's always the
  following fallback: I run a local proxy, which Crossroads chooses
  whenever nothing else is available. </li>

</ul>

Works like a charm. This is one of the "obscure (ab)uses of
Crossroads" as described on the
<a href="http://xrforum.org/viewtopic.php?t=61" target="_blank">XR
forum</a>.

<p/> Anyway, for the last part of this setup -the local proxy- I was
always using Squid, which is fast and works well. Squid however has
one major drawback: it caches DNS servers and results in such a way,
that when my laptop goes into sleep mode and when I later wake it, I
very often have to restart Squid to get it working again. I suspect
that a Squid instance caches its DNS servers, and when I wake up the
laptop on another network, DNS changes - but Squid doesn't find out
about it. Bummer.

<p/> Just yesterday I found out about this wonderful lightweight proxy
that fits my needs. It's a Perl module called
<a href="http://search.cpan.org/~book/HTTP-Proxy-0.24/lib/HTTP/Proxy.pm"
target="_blank">HTTP::Proxy</a>, which is just oh-so simple to use
and works. Incase you're interested - here's a small start script to
fire it up. It makes sure that the Perl proxy is started on port 3128
(the Squid port) and that information is logged to the system log
(usually <i>/var/log/messages</i> or <i>/var/log/system.log</i>). If
you want to run this:

<ul>

  <li> As user <i>root</i>, install the module <i>HTTP::Proxy</i>.
  Type <i>cpan</i> to access the Perl archive, then type <i>install
  HTTP::Proxy</i>, and finally quit the cpan program. </li>

  <li> Save the below script as e.g. <i>/usr/local/bin/ppproxy</i>.
  Make it executable using <i>chmod +x
  /usr/local/bin/pproxy</i> </li>

  <li> Finally, to start it... type <i>/usr/local/bin/pproxy &amp;</i></li>

</ul>

Here's the script!

<pre>#!/usr/bin/perl

use HTTP::Proxy qw(:log);
use strict;

# Remove any pre-exising downstream proxy definitions.
for my $e qw(http_proxy https_proxy ftp_proxy) {
    $ENV{$e} = undef;
}

# Set up the logger
my $of;
if (-x '/usr/bin/logger') {
    open ($of, '|/usr/bin/logger -t pproxy')
      or die ("Cannot start logger pipe: $!\n");
} else {
    open ($of, '&gt;&gt;/tmp/pproxy.log')
      or die ("Cannot write /tmp/pproxy.log: $!\n");
}

# Instantiate and initialize proxy
my $proxy = HTTP::Proxy-&gt;new(port =&gt; 3128);
$proxy-&gt;logfh($of);
$proxy-&gt;logmask(PROXY | STATUS);

# Run tha proxy!
$proxy-&gt;start();
</pre>

</p> <b>Update:</b> This is an improvement over using Squid in my
small setup - cuz what I need is a really small proxy. Unfortunately,
this setup also suffers from faults after a sleep/wake cycle of my
laptop. It appears that after waking, DNS entries of the proxy are no
longer correctly resolved. Hmmm... Might code it myself in C++. More
info to follow...
 
</description>
   </item>
   <item>
    <title>Avatar the Movie</title>
    <link>http://www.kubat.nl/pages/blogaria/154#154</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 By now you've probably seen Avatar. I recently heard that it hit the
one-billion dollar mark - great revenue, and I admit, impressive
movie, great graphics. I enjoyed watching it.

<p/> I'd recently heard two interesting remarks: First, that it's
pretty weird that the most advanced movie technology was used to make
a movie which basically is anti-technology. Yep, there's a funny
cynical twist right there.

<p/> I saw the second reaction
on <a href="http://failblog.org/2010/01/10/avatar-plot-fail/"
target="_blank">failblog.org</a>, where I hang out sometimes to get a
laugh or two. Here it is:

<center>
  <img src="/bld/epic-fail-avatar-plot-fail.jpg"/>
</center>

For the indexing inclined:

<p/>
<i>

  <center>
    <del>Disney's</del> James Cameron's<br/>
    <del>Pocahontas</del> Avatar!
  </center>
  <br/>

  In <del>1607</del> 2154, a ship carrying J<del>ohn</del>ake
  S<del>mith</del>ully arrives in a lush "new world" of <del>North
  America</del> Pandora. The settlers are mining for <del>gold</del>
  unobtanium, under supervision of <del>Governor
  Ratcliffe</del> Colonel Quaritch</del>. <del>John Smith</del> Jake
  Sully begins exploring the new territory, and
  encounters <del>Pocahontas</del> Neytiri. Initially she is
  distrustful of him, but a message from <del>Grandmother
  Willow</del> the Tree of Souls helps her overcome the trepidation.
  The two begin spending time together. <del>Pocahontas</del> Neytiri
  helps <del>John</del> Jake understand that all life is valuable, and
  how all nature is a connected circle of life. Furthermore she
  teaches him how to hunt, <del>grow crops</del> tame dragons, and of
  her culture. We find that her father is Chief <del>Powhatan</del>
  Eytucan, and that she is set to be married to <del>Kocoum</del>
  Tsu'Tey, a great warrior, but a serious man,
  whom <del>Pocahontas</del> Neytiri does not desire. Over
  time, <del>John</del> Jake and <del>Pocahontas</del> Neytiri find
  they have a love for each other. Back at the settlement, the men,
  who believe the natives are savage, plan to attack the natives for
  their <del>gold</del> unobtanium. <del>Kocoum</del>Tsu'Tey tries to
  kill <del>John</del> Jack out of jealousy, but he is later killed by
  the settlers. As the settlers prepare to attack, <del>John</del>
  Jack is blamed by the <del>indians</del> Na'vi, and is sentenced to
  death. Just before they kill him, the settlers arrive.
  Chief <del>Powhotan</del> Eytucan is <del>nearly</del> killed,
  and <del>John</del> Jake sustains injuries from <del>Governor
  Ratcliffe</del> Colonel Quaritch, who is then <del>brought to
  justice</del> shot with arrows. <del>Pocahontas</del> Neytiri risks
  her life to save <del>John</del> Jack. <del>John</del> Jack
  and <del>Pocahontas</del> Neytiri finally have each other, and the
  people resolve their differences.

</i>

<p/> Brilliant, Matt Bateman wherever you are! (And with apologies to
the Film Actors Guild and other groups for misspelling names...)
 
</description>
   </item>
   <item>
    <title>Slightly NSFW Linux Ad</title>
    <link>http://www.kubat.nl/pages/blogaria/153#153</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <i>Linux desktop domination</i> has been on the free software agenda
for a long time. Maybe these guys have found a way to make the
Phaenguin irresistably popular?

<p/>
<center>
  <img src="/bld/WalkingLinuxAd.jpg"/>
</center>
 
</description>
   </item>
   <item>
    <title>WTF</title>
    <link>http://www.kubat.nl/pages/blogaria/152#152</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/watch1.jpg" class="floatright"/>No, the abbreviation in the title isn't what you thought it is. It's
 <a href="http://thedailywtf.com/" target="_blank">Worse Than
Failure</a>, one of my fav sites where I go to cheer up a bit.

<p/> Quite recently I came across a great WTF code snippet in
Javascript. I encountered this beauty in the codebase of webpages at a
customer of mine. The code somehow tries to determine a hostname and
URL where a next page is located, and ultimately will send the user
there, using Javascript's <i>document.location</i> property. Without
further ado here's a snippet. Note, I replaced actual Internet-facing
servernames with <i>sever1</i>, <i>server2</i> and so on, to protect
the guilty.

<pre>
    newpage = newpage + parseString;
    newtarget = '';
    //alert("Incoming webservername: " + webservername);
    //Intranet
    if ( webservername == "server1.com" ) {
        webservername = "server1.com";
    } else if ( webservername == "server2.com" ) {
        webservername = "server2.com";
    //Internet
    } else if ( webservername == "server3.com" ) {
        webservername = "server3.com";
    } else if ( webservername == "server4.com" ) {
        webservername = "server4.com";
    } else {
        if (prefix) {
            newtarget = prefix + "://";
        }
        newtarget = newtarget + webservername + webserverport + newpage;
    }
    if (newtarget == '') {
        newtarget = "https://" + webservername + newpage;
    }
    //alert("New target: " + newtarget);
    return newtarget;
</pre>

WTF?<br/>
<i>if (a == 3) a = 3; <br/>
else if (a == 4) a = 4;</i> ??

<p/> But wait, there's more. This Javascript sourcefile was only
deployed on <i>some</i> of the servers (production and
pre-production). Testing had it's own version:

<pre>
    newpage = newpage + parseString;
    newtarget = '';
    //alert("Incoming webservername: " + webservername);
    //Test environment intranet
    if ( webservername == "server5.com" ) {
        webservername = "server5.com";
    } else if ( webservername == "server6.com" ) {
        webservername = "server6.com";
    } else if ( webservername == "server7.com" ) {
        webservername = "server7.com";
    } else if ( webservername == "server8.com" ) {
        webservername = "server8.com";
    //Test environment internet
    } else if ( webservername == "server9.com" ) {
        webservername = "server.com";
    } else if ( webservername == "server10.com" ) {
        webservername = "server10.com";
    } else if ( webservername == "server11.com" ) {
        webservername = "server11.com";
    } else if ( webservername == "server12.com" ) {
        webservername = "server12.com";
    } else {
        if (prefix) {
            newtarget = prefix + "://";
        }
        newtarget = newtarget + webservername + webserverport + newpage;
    }
    if (newtarget == '') {
            newtarget = "https://" + webservername + newpage;
    }
    //alert("New target: " + newtarget);
    return newtarget;
</pre>

And of course there's another Javascript source for yet more
servers... Sigh. During deployments, the people had to copy one of the
source files to the destination javascript source that would get
picked up by the pages. Which would of course lead to errors - during
deployments, one should always try to avoid non-automatic steps.

 
</description>
   </item>
   <item>
    <title>Stop Software Patents in the EU</title>
    <link>http://www.kubat.nl/pages/blogaria/151#151</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Gotta support this. So, all sign! (I saw this on <a
href="http://eddie.niese.net/20100105/petition-against-european-software-patents/"
target="_blank">Eddie's Blog</a>, so I'm shamelessly repeating it.
Which is in the spirit of this petition.)

<p/>
<center>
<a href="http://petition.stopsoftwarepatents.eu/671002623997/"
target="_blank"><img 
src="http://petition.stopsoftwarepatents.eu/banner/671002623997/ssp-732-121.gif"
alt="stopsoftwarepatents.eu petition banner"
width="732" height="121" /></a>
</center>

 
</description>
   </item>
   <item>
    <title>HammerServer 1.02</title>
    <link>http://www.kubat.nl/pages/blogaria/150#150</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Whee! I've been quite recently playing around
with <a href="couchdb.apache.org/" target="_blank">CouchDb</a>. It's
really neat and nice: a networked, document-oriented database that
does simple things, and does them really well: storing stuff, and
letting you retrieve it. It doesn't provide referential integrity or
built-in types - everything is just a string - but it's scalable and
reliable, it's got built-in features for replication and what not. All
stored documents are even automatically versioned and revisioned, so
that data can always be rolled back to a previous state.
Interesting!

<p/> And if you happen to like Perl, the
module <a href="http://search.cpan.org/~dgl/Net-CouchDb-0.01/"
target="_blank">Net::CouchDb</a> will make your life really a lot
easier. Great fun to play with.

<p/> So to get some practical fun with CouchDb, I incorporated it as a back
end type in my
tamper-resistant <a href="/pages/hammerserver">HammerServer</a>. By
definition, there is more network overhead when storing data in
CouchDb, since all is sent over HTTP. So when compared to a flat file, or a
PostgreSQL database, CouchDb is slower. However, CouchDb's strenghts
should become apparent when the datastore is spread over many nodes
which balance-out inserting and retrieving records (which I didn't try
out).

<p/> So if you like, have a look
at <a href="/pages/hammerserver">HammerServer 1.02</a>.

<p/> One of the fun things I found was the following. The HammerServer
relies on sequential ID's to store data. Each record at a given ID is
signed using its own data, but also using the signature of the
previous ID (which is ID-1). This is done to form a "chain" of secure
data, where deletions and insertions are detected. Therefore, the
correct working of the HammerServer relies on atomic increments of
some ID counter. Concurrent requests to insert new data may never wind
up using the same ID!

<p/> In RDBMS terms this is easily accomplished as something like:

<pre>select nextval(sequence)</pre>

or in Oracle terms,

<pre>select sequence.nextval from dual</pre>

The problem is that CouchDb is a document-oriented datastore, meaning
that making such an operation atomic isn't straight forward. In any
case, such an atomic update isn't built in. How can the
application enforce atomic operations in CouchDb, to avoid
concurrency-issues?

<p/> A too simplistic application-oriented attempt might be:

<ul>
  
  <li>Initially, create a document in the database, named
  e.g. <i>lastid</i>, with a data element <i>nr</i> initialized to the
  value 0.</li>

  <li>When getting the next value, the process might be:

    <ul>
      
      <li>Fetch the document <i>lastid</i> from the database,</li>
      <li>Get its field <i>nr</i>,</li>
      <li>Increment it,</li>
      <li>Write it back to the database.</li>
      
  </ul></li>
</ul>

The problem here is of course that this approach isn't designed to be
atomic. Two concurrent requests might get the same ID, which would
break HammerServer's security.

</p>Fortunately, CouchDB's revisioning comes to the aid. Internally
CouchDB also fetches revision data from the database when a document
is requested. When the same document is sent back for storage, the
revision data must still match - else, CouchDB issues an error stating
that there is a revision conflict. Brilliant! The right pseudo-code is
then:

<ul>
      
  <li>Fetch the document <i>lastid</i> from the database,</li>
  <li>Get its field <i>nr</i>,</li>
  <li>Increment it,</li>
  <li>Attempt to write it back to the database,</li>
  <li>If there is a conflict error, then redo all - starting at the
  top.</li>
  <li>Otherwise we're done, the last value of <i>nr</i> is the
  atomically incremented ID. </li>

</ul>

The HammerServer furthermore spices it up by retrying for no more than
60 seconds (just incase there's something really wrong at the back
end). As an example here is some Perl code that
uses <i>Net::CouchDb</i> to illustrate this. In the real HammerServer
sources the code is quite different and you can find it in the
method <i>getnextid()</i> of <i>mod/db/CouchDB.pm</i>. The below code
is only an illustration of the concept.

<pre>
# Connect to the CouchDb server
my $connection = Net::CouchDb->new('http://hostname:5984')
  or die("Can't connect to server\n");
# Connect to the database
my $cdb = $connection->db('database')
  or die("Can't connect to the database\n");

# The next ID to determine:
my $nextid;

# Fetch the "lastid" document, increment the field "nr". If an update
# conflict occurs, then redo until we're out of time. Oh, and die if
# some other weird error occurs.
my $start_t = time();
my $try = 1;
while (1) {
    # Fetch the counter document, increment number.
    my $doc = $cdb->get('lastid');
    $doc->nr += 1;

    # Write it back to the database.
    print("Try $try: incrementing to ", $doc->nr, "\n");
    my $result = $cdb->post($doc)
      or die("Failed to re-contact the CouchDB server\n");
    if ($result->{ok}) {
	# Data committed. We're done.
	$nextid = $doc->id;
	last;
    } elsif ($result->{error} eq 'conflict') {
	# Conflict error. Die miserably if this has been going on
	# for 60 seconds or more.
	die("Failed to increment lastid counter after 60 sec\n")
	  if (time() - $start_t > 60);
	# The 1 min hasn't elapsed yet, let's retry.
	print("Concurrency error, retrying\n");
	next;
    } else {
	# Some other error.
	die("CouchDB error: ", $res->{error}, ' ',
	    $res->{description}, "\n");
    }
}

# All done.
print("ID succesfully and atomically incremented to $nextid\n");
</pre>

Conclusion: Yep this works like a charm. I only had to fire up two
"trains" of insertion requests to detect logfile messages stating that
retries were necessary. All in all, this approach is perfectly
feasible. One might say: yech, that's a lot of work to just
emulate <i>select nextval(sequence)</i>. True. On the other hand,
consider that CouchDb's philosophy is that tasks - and hence code and
complexity - should be "pushed out" towards calling applications, so
that the central database can remain lean and mean and fast. That
argument is as good as any.
	
 
</description>
   </item>
   <item>
    <title>Perls Automagical Autoloading</title>
    <link>http://www.kubat.nl/pages/blogaria/149#149</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This will quite likely be already loooong known to all Perlmonks in
the world, but hey. I just found out the possibility to
"automagically" create methods for Perl classes, and I'm happy...

<p/> Before, I used to write getters and setters for all data fields
in my Perl classes. For example:

<pre>package Animal;
sub new {
    # ...
}

sub name {
    my ($self, $val) = shift;
  
    # If $val is given then this method is considered a
    # 'setter': store the value in this object.
    $self->{name} = $val if ($val);

    # Now do the 'getter' thing, return the contained data.
    return $self->{name};
}</pre>

The purpose of such an accessor method is of course that you can have
on object of the type <i>Animal</i> and you can use the
method <i>name()</i> to either set or get the name - so its a getter
and a setter at the same time:

<pre>my $dog = Animal->new();
$dog->name('Spot');
print("My dog is named ", $dog->name(), "\n");</pre>

The above stanza could be rewritten in terms of the array of method
arguments <i>@_</i>, hence using <i>$_[0]</i> to address 'self', and
using <i>$_[1]</i> to address the (optional) 'val'. This gives us
somewhat shorter, though cryptical code (but isn't a really meaningful
improvement):

<pre>sub name {
    $_[0]->{name} = $_[1] if ($_[1]);
    return $_[0]->{name};
}</pre>

In general, this getter/setter approach works just fine: one uses
datafields <i>$self-&gt;{whatever}</i> to store data, and wrapper
methods <i>$object-&gt;whatever()</i> are accessors: when the accessor
has an argument then it's assumed a setter, else just a getter.

<p/> The only drawback of this approach is that classes tend to
contain a lot of repetitive code. The above hypothetical <i>Animal</i>
would have a method <i>name()</i> to wrap a datafield <i>name</i>,
next it might have a method <i>nr_of_legs()</i> to wrap a
datafield <i>nr_of_legs</i>, and so on. You get the idea.

<p/>

Wouldn't it be nice if, when coding the class, one wouldn't have to
hand-craft such repetitive getters and setters? Well, exactly this is
possible using Perl's automagical autoloading. Here's how it works:

<ul>

  <li>When a non-existing method is called on an object, Perl tries to
  invoke the method <i>AUTOLOAD</i> (if such method exists).</li>

  <li>Whilst doing so, the invoked name is stored in a class
  variable <i>$AUTOLOAD</i> (if such a variable exists).</li>

  <li>Hence, if you craft a method <i>AUTOLOAD</i>, which inspects a
  variable <i>our $AUTOLOAD</i> to find out the non-existing name, then
  that method can emulate what the non-existing getter/setter should
  be doing!</li>

</ul>

It's like dynamically creating methods when they're needed. Or
magically opening a window where there first was a solid wall!

<p/> Time for an example. You can download the below code
as <a href="/automagic.pl">automatic.pl</a>. The code has in one file
a package called <i>Generic</i>, where the automagic is implemented.
Then the code is tested below that. I wonder if Donald Fagen had such
fine automated aids to help him with his text writing?

<pre>
#!/usr/bin/perl

use strict;

{
    package Generic;

    sub new {
	my $class = shift;
	my $self = {};
	bless($self, $class);
	return $self;
    }

    our $AUTOLOAD;
    sub AUTOLOAD {
	my ($self, $val) = @_;
	$self->{$AUTOLOAD} = $val if ($val);
	return $self->{$AUTOLOAD};
    }

    1;
}

my $r = Generic->new();
$r->title('girl');
$r->name('Ruby');
$r->lacks('pretty');
$r->question('when will you be mine');

print("I've got a ", $r->title(), " and ", $r->name(), " is her name\n",
      "She ain't real ", $r->lacks(), " but I love her just the same\n",
      $r->name(), " ", $r->name(), " ", $r->question(), "?\n");
</pre>

<b>First Update:</b> I forgot to mention that the exact value of the
variable <i>our $AUTOLOAD</i> is <i>class::method</i>. The autoload method
can therefore verify against unwanted getters/setters, as thus:

<pre>
# Standard stuff...
package Generic;
sub new {
    # ...
}

# Autoload version that allows only getter/setters title, name, lacks
# and question. All others are considered an error. You get the idea..
our $AUTOLOAD;
sub AUTOLOAD {
    my ($self, $val) = @_;

    # These are the allowed methods
    my %allowed = (title => 1, name => 1, lack => 1,
		   question => 1);

    # Here's the requested method: $AUTOLOAD without method name
    my $requested = $AUTOLOAD;
    $requested =~ s{.*::}{};

    # Check that this is allowed..
    die("Method not allowed\n") unless ($allowed{$requested});

    # Do the automagic.
    $self->{$requested} = $val if ($val);
    return $self->{requested};
}
</pre>
  
<b>Next update:</b> Be sure to use <i>our $AUTOLOAD</i> and
not <i>my</i>. Made that mistake myself and was searching for at least
30 seconds for the fault.
 
</description>
   </item>
   <item>
    <title>Office Poster</title>
    <link>http://www.kubat.nl/pages/blogaria/148#148</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen on the Cheezeburger Network (more precisely
<a href="http://punditkitchen.com/2009/10/07/political-pictures-tornado-gonna-suck/" target="_blank">punditkitchen.com</a>):

<p/>
<center>
  <img src="/bld/political-pictures-tornado-gonna-suck.jpg"
       alt="Wel... this is gonna suck"/>
</center>

<p/> My Office Poster for next week!
 
</description>
   </item>
   <item>
    <title>The nr 1 Nerdjoke</title>
    <link>http://www.kubat.nl/pages/blogaria/147#147</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This one ranks number one in my collection of nerdjokes.

<p/>
<i>Two hydrogen atoms are walking down the street.<br/>
Atom 1: "Damn, I lost my electron again."<br/>
Atom 2: "You sure?"<br/>
Atom 1: "Yeah, I'm positive."</i>
 
</description>
   </item>
   <item>
    <title>WoW Startscript for my Mac</title>
    <link>http://www.kubat.nl/pages/blogaria/146#146</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I wrote before about how <a href="/pages/blogaria/122#122">I needed to
reinstall World of Warcraft on a non-casesensitive partition</a>
because of WoW patch nr. 3. So since then, basically, I must mount a
disk, navigate to the game executable, and double-click it to play

<p/> Well, I'm a keyboard type of guy and I hate clicking around. So
all this of course can be scripted. It's all really very simple, but
hey, maybe the below example will inspire someone to do their own
scripting of repetitive tasks.

<p/> The script is appropriately called <i>wow</i> and it accepts
arguments:

<ul>

  <li><i>wow start</i> mounts the disk and starts the game (in the
  back ground);</li>

  <li><i>wow end</i> kills the game if it's running and unmounts the
  disk;</li>

  <li><i>wow</i> (without arguments) mounts the disk, starts the game,
  waits for it to finish, and unmounts the disk.</li>

</ul>

The script uses the MacOSX command "open" to do its magic like
mounting disks and starting apps. The <i>open</i> command is actually
very versatile and worth taking a look at. From the help information:

<pre>Usage: open [-e] [-t] [-f] [-W] [-n] [-g] [-h] [-b &lt;bundle identifier&gt;] [-a &lt;application&gt;] [filenames]
Help: Open opens files from a shell.
      By default, opens each file using the default application for that file.  
      If the file is in the form of a URL, the file will be opened as a URL.
Options: 
      -a                Opens with the specified application.
      -b                Opens with the specified application bundle identifier.
      -e                Opens with TextEdit.
      -t                Opens with default text editor.
      -f                Reads input from standard input and opens with TextEdit.
      -W, --wait-apps   Blocks until the used applications are closed (even if they were already running).
      -n, --new         Open a new instance of the application even if one is already running.
      -g, --background  Does not bring the application to the foreground.
      -h, --header      Searches header file locations for headers matching the given filenames, and opens them.</pre>

<p/> In this case, my script only uses <i>open &lt;diskimage&gt;</i>
to mount an image, or uses <i>open &lt;application&gt;</i> to start an
app, or it uses <i>open -W &lt;application&gt;</i> to start an app and
wait for it to finish. Besides that, <i>disktool</i> is used to
unmount a disk image.

Well, here's the script. Hope it's somewhat useful to you. Mind that
if you want to use this, you'll have to edit the configuration at the
top of the script.

<pre>#!/bin/sh

# Another little proggle to make my life easier. This time a shell script
# that starts my favorite game, WOW. I have the game on a separate disk
# image. So when I want to play, I need to (a) mount the image, (b) start
# the game and play it, and (c) unmount the image as a cleanup. That's what
# this lil'script does.

# Configuration - edit at will. Specify the disk image, the mount point
# of the image, and the application (inside the image). You can find these
# out by locating your game image by hand, and by mounting it using the
# Finder. Then in /Volumes you'll see the mountpoint. The app is located
# somewhere inside the mountpoint.
image=/private/images/WOW.sparseimage
mountpt=/Volumes/WOW
app="$mountpt/World of Warcraft/World of Warcraft.app"
# End of configuration. The rest should need no tweaking.

# Mount the game image onto the mount point
function mountdisk() {
    if [ ! -d "$mountpt" ] ; then
        echo "Mounting $image"
        open -W "$image" || exit 1
        if [ ! -d "$mountpt" ] ; then
            echo "Failed to mount $image to $mountpt"
            exit 1
        fi
    fi
}

# Run the game app off a mounted image
function runwow() {
    echo "Starting $app"
    if [ ! -d "$app" ] ; then
        echo "Failed to locate $app"
        exit 1
    fi
    open "$1" "$app"
}

# Stop the game (kill the process)
function stopwow() {
    pid=`ps  ax | grep World | grep -v grep | awk '{print $1}'`
    if [ -z "$pid" ] ; then
        echo "Not running, nothing to stop"
    else
        echo "Stopping pid $pid"
        kill "$pid"
    fi
}

# Unmount the game image
function umountdisk() {
    disk=`disktool -l | grep "$mountpt" |
    awk '{print $3}' | awk -F\' '{print $2}'`
    if [ -z "$disk" ] ; then
        echo "No disk in use, not ejecting"
    else
        echo "Unmounting disk $disk"
        disktool -u "$disk" >/dev/null
    fi
}

# Main starts here, depending on the argument the above functions are
# called
if [ "$1" == "start" ] ; then
    mountdisk
    runwow
elif [ "$1" == "stop" ] ; then
    stopwow
    umountdisk
elif [ -z "$1" ] ; then
    mountdisk
    runwow -W
    umountdisk
else
    cat &lt;&lt;EOF

Usage: wow start : starts the game (as a background process)
   or: wow stop  : stops a previously started game and cleans up
   or: wow       : starts, wait for the game to stop, cleans up

Game image expected as : $image
Mount point            : $mountpt
Game application       : $app
   
EOF
fi</pre>

 
</description>
   </item>
   <item>
    <title>HammerServer section is online</title>
    <link>http://www.kubat.nl/pages/blogaria/145#145</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/watch2.jpg" class="floatright"/>
I just posted the docs for
the <a href="/pages/hammerserver">HammerServer</a>: a networked daemon
that serves as an audit-log, but it's tamper-resistant (can't touch
this). It's a pretty nice proof of concept thingy I think that can be
used as a stepping stone for specific ideas and requirements.
 
</description>
   </item>
   <item>
    <title>The BING HQ</title>
    <link>http://www.kubat.nl/pages/blogaria/144#144</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 
<img src="/bld/bing.jpg"/>
 
</description>
   </item>
   <item>
    <title>Digging a WOW Tunnel</title>
    <link>http://www.kubat.nl/pages/blogaria/143#143</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <h1>Digging a WOW Tunnel</h1>

<img src="/bld/k/bignose2.jpg" class="floatright"/>
If you ever find yourself on a firewalled network that has just an
outgoing proxy, and still feel the urge to connect to WOW, then here's
how. This text shows how to make sure that you can log on, and use the
regular play. 

<h2>Ingredients</h2>

You will need:

<ul>
  
  <li> A Unixy system, like a Macbook or a Linux box. On this system
  you'll need <i>root</i> privileges so you can
  edit <code>/etc/hosts</code>, run <code>ifconfig</code> etc. </li>
  
  <li> A server on the outside that is Internet-connected and where
  you can run remote SSH commands. Verify this in advance by
  running e.g.
    
    <pre>ssh USER@HOST ls</pre>

  This should of course show the <code>ls</code> output of the stated
  user's home directory. Substitute appropriate values for USER and
  HOST.
    
  <p/> In the next sections I'm assuming that you have your local SSH set
  up so that it tunnels-out via the proxy (hints: Configure this
  in <code>~/.ssh/config</code> and use <code>ProxyCommand
  proxytunnel</code>).</li>

  <li> Also you'll need to know the hostname of the Blizz logon
  server, which is in my case <i>eu.logon.worldofwarcraft.com</i>.

  <li> Finally you will also need to know the IP address of your game server.
  For me it's Bloodhoof, which resides on <i>80.239.179.103</i>. If
  you don't know this IP address, then you'll just have to sniff it
  off the network using <i>wireshark</i>.
  </li>

</ul>

<h2>Approach</h2>

Basically, you'll have to do the following tasks:

<ul>

  <li> Make sure that the WOW client will talk to your local machine
  as login server; </li>

  <li> Forward this traffic to the true logon server using SSH; </li>

  <li> Grab the IP of the realm server and assign it to your
  localhost, so that the WOW client will talk to your local machine to
  enter the world;

  <li> Forward this traffic to the real server over SSH.</li>

</ul>

<h2>Recipy</h2>

<ul>

  <li> Edit <code>/etc/hosts</code> and add the line:

    <pre>127.0.0.1 eu.logon.worldofwarcraft.com</pre>

  </li>

  <li> Start forwarding this traffic to the real logon server, using
  the command:

    <pre>ssh -v -N -L 127.0.0.1:3724:eu.logon.worldofwarcraft.com:3724 USER@HOST</pre>

  Supply the right SSH user and host in the command. </li>

  <li> Grab the IP of the realm server:

    <pre>ifconfig lo0 alias 80.239.179.103</pre>

  </li>

  Note that <code>lo0</code> is the loopback device on MacOSX. On a
  Linux box this would be <code>lo</code>.

  <li> Start forwarding the traffic of your new local IP address
  80.239.179.103 to the real logon server, using the command:

    <pre>ssh -v -N -L 80.239.179.103:3724:80.239.179.103:3724 USER@HOST</pre>

  </li>

</ul>

<h2>Undoing</h2>

To turn this back, edit <code>/etc/hosts</code> and comment-out the
line that redefines the IP address
for <i>eu.logon.worldofwarcraft.com</i>.

<p/> To remove the binding of the IP address 80.239.179.103, run as
root:

  <pre>ifconfig lo0 -alias 80.239.179.103</pre>
 
</description>
   </item>
   <item>
    <title>Wee Todd</title>
    <link>http://www.kubat.nl/pages/blogaria/142#142</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This was put to me by <a href="http://beerholder.blogspot.com/"
			 target="_blank">BOFH</a> at a barbecue:

<p/>
<quote>
  <i>
    I'm wee todd <br/>
    I'm sofa king<br/>
    I'm wee todd did</br>
  </i>
</quote>

<p/>
Well, I got the second line right...
 
</description>
   </item>
   <item>
    <title>The On Off Switch Revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/141#141</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I had to see my server that's colo-hosted to fix some things.
The server had a very nasty habit of not booting up after a crash or
power interruption. Time to fix it up, I thought. Well, that wasn't
such an easy task. Here's why....

<p/>
<img src="/bld/Switch2.jpg" class="floatright"/>It's <a href="http://www.kubat.nl/pages/blogaria/25#25">the on/off
switch</a> but revisited. Following my first blog I'd wisened up, I
nowadays check the BIOS on server systems. Usually there's an option
that says something like "reboot after power failure". Once this
option is enabled, the server will happily boot the OS when it gets
back power, instead of staying in stand-by mode. And that of course is
basically what you always want: an unattended system should simply
come up after a power failure, and not wait for a human to come press
a button.

<p/>
So of course, with this current server, I started the system, went
into the BIOS screen, and looked for a similar option. To no avail.
This server is an IBM e-server, model 330, and it doesn't have
such a feature. I spent an hour looking for something like this, and
came up with zip. Finally after googling for 15 minutes, I got a brainwave.

<p/> The e-server family of IBM's rack models has a counter in its
BIOS that stores how many times the server has succesfully booted
(after a planned reboot) and how many times it rebooted after a crash.
If the server experiences too many crashes then the ratio of crashes
vs. planned boots tells it not to boot anymore, but to go into
standby mode. AAAAAAAAAAAAAAAAAAAARGGH!!

<p/> This is so totally braindead. Imagine that you're using a stable
OS that doesn't need rebooting. Then the only downtime you'll ever
experience will be due to hardware crashes, or due to power outages.
Which means that there will be more crashes than planned reboots. So,
the server decides for you that it's better to go into standby mode
after a while.

<p/>
Fortunately there is a BIOS setting to disable this behavior, but you
have to really know about it before you find it. Well, I should've
suspected something like that. Rack system or not - Big Blue will of
course assume that you're running Windows and that you reboot your
system regularly, by choice. How braindead can you get.

<p/> This reminds me of the following funny. The image should also
have the following caption: "But IBM thinks I'm getting laid all the
time."

<p/>
<center>
  <img src="/bld/UnixNotGettingLaid.jpg"/></center>


 
</description>
   </item>
   <item>
    <title>Meatspace</title>
    <link>http://www.kubat.nl/pages/blogaria/140#140</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today
on <a href="http://tech.slashdot.org/story/09/06/21/1954215/Where-Does-a-Geek-Find-a-Social-Life">Slashdot</a>:

<p/>
<img src="/bld/MeatSpace1.png"/>
<p/>
And then there was of course the obvious answer. Marked "insightful"?
LOLZ!

<p/>
<img src="/bld/MeatSpace2.png"/>
<p/>
"Meatspace.." I must confess, I'd never heard that one before!
 
</description>
   </item>
   <item>
    <title>My old houses</title>
    <link>http://www.kubat.nl/pages/blogaria/139#139</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 While giving lectures at the State Univ. of Groningen, I took the
opportunity to see two of my old houses. The first one is where I used
to live as a student. I had some great times there with all the other
guys and girls who lived there...

<p/>
<img src="/bld/WH1.jpg"/>
<p/>
The second one is actually my first ever owned house. Great place it
was..

<p/>
<img src="/bld/RV2.jpg"/>
<p/>
That brings back loads of sweet memories...

 
</description>
   </item>
   <item>
    <title>LOLcats are funny</title>
    <link>http://www.kubat.nl/pages/blogaria/138#138</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <a href="http://icanhascheezburger.com/" target="_blank">LOLcats</a>
are very funny at times. Here's a long time favorite of mine.

<p/>
<center>
  <img src="/bld/funny-pictures-your-child-watched-too-many-zombie-movies.jpg"/></center>
 
</description>
   </item>
   <item>
    <title>Civic Duty WIN</title>
    <link>http://www.kubat.nl/pages/blogaria/137#137</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <a href="http://www.failblog.org">Www.failblog.org</a> is classifying
this as a "fail". I don't get it, why not a "win"? In particular, the
following phrasing signals a win in my view: "Jury duty is a complete
waste of time. I would rather count the wrinkles on my dogs balls than
sit on a jury. Get it through your thick skulls. Leave me the f–k
alone."

<p/>At the least, this guy is outspoken. Loose or win?

<p/>
<img src="/bld/CivicDuty.png"/> 
</description>
   </item>
   <item>
    <title>Vote for the baby, Sky Radio promo FAIL</title>
    <link>http://www.kubat.nl/pages/blogaria/136#136</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The Dutch / British station "Sky Radio" is apparently holding a contest "Vote
for my baby". You enter your little toddler, and they've got a chance
to win ... what? I've no idea, clothes, a walker, a wooden horse? No
idea, really. But this struck me as odd:

<p/>
<img src="/bld/VoteForTheBaby.png"/><p/>

I've got 6 hours and something before I should start voting. Or 364
days. Year-wrap gone bad, anyone?

<p/>
Geez, giant suck.
 
</description>
   </item>
   <item>
    <title>My secure data center</title>
    <link>http://www.kubat.nl/pages/blogaria/135#135</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This all started as follows. A good customer of mine
needed <b>quickly</b> a terabyte of secure storage, to store some
old files for audit reasons. The storage would be put in a vault, just
incase. The requirements were that the storage media should be very
secure, and should be detachable - so that all could go in a vault.

<p/> The inhouse ICT club of course offered a fantastic solution,
secure, redundant and all that - for a truckload of cash, and it would
be ready in a month. I don't even think that the money would've been
an issue, but the storage was needed "yesterday", not in a month.
Well, that's how things go.

<p/> Enter the DYI method of Secure Data Center Installations. For starters,
you need an old HP desktop, converted to Ubuntu, to which two Terabyte
USB disks are attached. The two disks set us back about EUR 160. We of
course encrypted both disks using Truecrypt and hooked them up. One of
the disks is used as write media for whatever files need to be stored,
the other is a back up which is rsynced every so often. Hey, if it
needs to be stored for some time, we'd better have two..

<p/>
<table>
  <tr>
    <td>
      <img src="/bld/SDCdesktop.jpg"/> <br/>
      <i>A standard desktop that we cannibalized...</i>
    </td>
    <td>
      <img src="/bld/SDCusbdrive.jpg"/> <br/>
      <i>With a USB drive plugged in...</i>
    </td>
  </tr>
</table>
<hr/>
<p/>

Next are of course physical security issues. Encryption is good, but
physical access restrictions aren't bad either. Plus I have to admit,
we didn't want this thingy to be noticed.. as in "Hey, what's that
system doing over there? Who hooked up them USB drives? What version
of Windows is it running? What? No standard Windows build? Li- what?"
So enter the Powertools. We commandeered a desk cabinet that was
previously used for paperwork, and drilled a few holes in the back for
cables. 

<table>
  <tr>
    <td>
      <img src="/bld/SDCpowertool.jpg"/> <br/>
      <i>Powertools make my day.</i>
    </td>
    <td>
      <img src="/bld/SDCholes.jpg"/> <br/>
      <i>They also make holes in the back.</i>
    </td>
  </tr>
</table>
<hr/>
<p/>

The slider mechanism in the cabinet, previously used for hanging paper
folders, made a nice support for a flat screen and a keyboard. Hey, a
Secure Cabinet with a retractable screen and keyboard - who would've
thought?

<table>
    <tr>
    <td>
      <img src="/bld/SDCslider.jpg"/> <br/>
      <i>Retractable!</i>
    </td>
    <td>
      <img src="/bld/SDCbooting.jpg"/> <br/>
      <i>It even boots.</i>
    </td>
  </tr>
</table>
<hr/>
<p/>

Here's the result. You'd never know there's a super-secret 1Tb
storage unit in here, being mirrored onto a redundant second 1Tb.
There was however one victim of all this: My one inch drill that I'd
used for the back of the cabinet. Totally burnt. Well, it'd done its
job, RIP...

<table>
    <tr>
    <td>
      <img src="/bld/SDCcabinet.jpg"/> <br/>
      <i>Super-secret. It's got a lock.</i>
    </td>
    <td>
      <img src="/bld/SDCdrill.jpg"/> <br/>
      <i>The one casualty.</i>
    </td>
  </tr>
</table>
<hr/>
<p/>

All in all? It made the office day a lot less boring!
 
</description>
   </item>
   <item>
    <title>My Valentine is sending me a dot exe</title>
    <link>http://www.kubat.nl/pages/blogaria/134#134</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
  <tr>
    <td valign="top">
      Happy Valentine's day, for sure. It's even a happier Valentine for
      spambots. They are breeding like crazy. 'Tis the time they send mails
      with links that try to get you to download an executable "greeting
      card viewer". Of course. What else is new?
    </td>
    <td width="388" valign="top">
      <img src="http://www.kubat.nl/bld/E-Greetings.png"/>
    </td>
  </tr>
</table>
 
</description>
   </item>
   <item>
    <title>MacPorts trash: .mp_123456 savefiles cleaning</title>
    <link>http://www.kubat.nl/pages/blogaria/133#133</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 As I was searching for some files on my hard disk, I saw I had a lot
of files named <i>*.mp_123456</i>, especially under the
directory <i>/opt/local</i>. The number (123456 in this example) can
of course be any other random number. A short investigation revealed
that those files are save-files from MacPort runs, that especially
appear during forced installations or activations, i.e., after <i>port
-f install ...</i>

<p/> So I decided to clean them up. For your pleasure, here's a little
script that does it. Save it as <i>mp-clean</i> somewhere on your
system, and run as:

<ul>

  <li>
    <b>mp-clean test</b>: This will scan your entire disk and
    report how many savefiles it finds, and their total size. It may run
    for a looooong time, so don't be impatient!

    <p/> A save-file is a file that ends in <i>.mp</i> followed by a
    number, and there must be a corresponding "real" file in the same
    directory. E.g., a
    save-file <i>/opt/local/include/hdr.h.mp_123456</i> is only a
    save-file if the corresponding
    file <i>/opt/local/include/hdr.h</i> exists.
  </li>

  <li>
    <b>mp-clean test /opt/local/include</b>: This is like the above,
    except that only <i>/opt/local/include</i> and its subdirectories
    are scanned.
  </li>

  <li>
    <b>mp-clean go</b> and <b>mp-clean go /opt/local/include</b> don't
    only locate the files and report their total size, but they also
    remove them. This is the actual cleaner.
  </li>

</ul>

Now, removing system files is always a bit scary. But hey, it saved me
some 50Mb diskspace and I haven't seen bad side effects yet.
Nevertheless, use it at your own risk and of course make sure you have
a backup before you run it...

<p/>
Finally, here's the little script.

<pre>#!/usr/bin/perl

use strict;
$|++;

# Command line
my $action   = shift(@ARGV);
my $startdir = shift(@ARGV);
$startdir = '/' if ($startdir eq '');
die ("Usage: mp-clean test|go [startdir]\n",
     "Cleans up mp-savefiles from port. Default startdir is /\n")
  if ($#ARGV != -1 or ($action ne 'go' and $action ne 'test'));

# Locate the mp files.
open (my $if, "find $startdir -name '*.mp_*' |")
  or die ("Cannot start find\n");
my $totfiles = 0;
my $mpfiles = 0;
my $bytescleaned = 0;
while (my $mpfile = <$if>) {
    $totfiles++;
    chomp ($mpfile);
    print ("$totfiles files seen (at $mpfile)\n");
    
    my $orgfile = $mpfile;
    $orgfile =~ s{\.mp_[0-9]+$}{};
    next unless (-f $orgfile);
    $mpfiles++;
    
    $bytescleaned += (stat($mpfile))[7];

    if ($action eq 'go') {
        unlink ($mpfile) or die ("\nCannot unlink '$mpfile': $!\n");
    }
}

print ("\n",
       "Found MP files:        $mpfiles\n",
       "Total size MP files:   $bytescleaned\n");</pre>

    
 
</description>
   </item>
   <item>
    <title>Truecrypt 6 on Linux and the ext3 filesystem</title>
    <link>http://www.kubat.nl/pages/blogaria/132#132</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 
I recently installed Truecrypt on a USB drive, attached to a Linux
box. It was Truecrypt version 6.1a. This version natively supports the
"FAT" filesystem, which is of course not what you want on a Linux box.

<p/> The GUI that drives Truecrypt doesn't really help when you want
to do "special" things, such as choosing a non-default filesystem for
the encrypted disk. Fortunately, Truecrypt is built in the best Unix
fashion - with a command line tool underneath, so that you get to
control all the detailed aspects! Here's a short description of how to
put an ext3 filesystem on a Truecrypt-protected disk.

<hr/>

<ul>

  <li>
    First, the disk is encrypted. In this example my USB drive
    is the device <i>/dev/sdb1</i>. Adjust where necessary. The
    encryption is started using

    <p/>
    <code>truecrypt -c /dev/sdb1</code>
    
    <p/> Truecrypt will then prompt for the encryption algorithm, hash
    size and so on. At the prompt for the filesystem, take FAT. This
    doesn't really matter, it will get overwritten later on. Next, go
    shopping, drink coffee, make lunch - this step takes a while. (My
    1Tb disk took 10 hours to encrypt.)
  </li>

  <li>
    Next, the disk is "mapped". Which is like mounting, except that
    the device isn't really attached to a physical directory. It's
    only mapped to a pseudo-device. Truecrypt is placed between the
    real device and the pseudo-device to take care of all encryption.
    The command is:

    <p/>
    <code>truecrypt /dev/sdb1  --filesystem=none</code>

    <p/> The specification that Truecrypt should assume "no
    filesystem" prevents the actual mounting.
  </li>

  <li>
    The raw encrypted device is now available as a pseudo-device. The
    following command shows which pseudo-device that is:

    <p/>
    <code>truecrypt --volume-properties</code>

    <p/> The output of this command shows a line like: <i>Virtual
    Device: /dev/mapper/truecrypt1</i>. In this case the virtual
    device is of course /dev/mapper/truecrypt1.
  </li>

  <li>
    The mapped virtual device can now be used to create a new
    filesystem in the encrypted device. In this case I'm going for
    "ext3":

    <p/>
    <code>mkfs.ext3 /dev/mapper/truecrypt1</code>
  </li>

  <li>
    Once the filesystem is there, the virtual device is released.
    After that, Truecrypt is used to re-map the device and now to
    truly mount it:

    <p/>
    <code>truecrypt -d</code><br/>
    <code>mkdir /mnt/encrypted   # a directory of your choice</code><br/>
    <code>truecrypt /dev/sdb1 /mnt/encrypted</code>
  </li>

</ul>

<p/>
<center>
  <i>
    As ever, <br/>
    If you have useful additions or comments, <br/>
    <a href="mailto:karel@kubat.nl">let me know</a>!
  </i>
</center>
    
 
</description>
   </item>
   <item>
    <title>www versus nl.youtube.com</title>
    <link>http://www.kubat.nl/pages/blogaria/131#131</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today when accessing www.youtube.com (I'm showing the HTTP
request and response headers):

<pre>GET / HTTP/1.1
Host: www.youtube.com
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.5) Gecko/2008120121 Firefox/3.0.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: UTF-8,*
Keep-Alive: 300

HTTP/1.x 302 Moved Temporarily
Transfer-Encoding: chunked
Date: Wed, 28 Jan 2009 14:29:06 GMT
Content-Type: text/html; charset=utf-8
Expires: Wed, 28 Jan 2009 14:29:06 GMT
Cache-Control: no-cache
Server: Apache
X-Content-Type-Options: nosniff
Location: http://nl.youtube.com/</pre>

Or, in normal English: When requesting the top page ("GET /") from
host www.youtube.com, the server says: Go to "http://nl.youtube.com".
OK, my browser thinks, let's check there:

<pre>GET / HTTP/1.1
Host: nl.youtube.com
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.5) Gecko/2008120121 Firefox/3.0.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: UTF-8,*
Keep-Alive: 300

HTTP/1.x 302 Moved Temporarily
Transfer-Encoding: chunked
Date: Wed, 28 Jan 2009 13:09:29 GMT
Content-Type: text/html; charset=utf-8
Expires: Wed, 28 Jan 2009 13:09:29 GMT
Cache-Control: no-cache
Server: Apache
X-Content-Type-Options: nosniff
Location: http://www.youtube.com/</pre>

Hahaha...

<p/> Anyway, even at Google there are sometimes problems. That's
comforting in a weird sort of way. Next time I mess up my webserver,
I'll know that I'm not the only one ;-)

<hr/>
[Update:] Checking back later, Youtube suggested to me a Dutch filter.
Might this be related to the endless redirection loop? Hmmm...

<p/> 
<img src="/bld/YouTube.png"/> 
</description>
   </item>
   <item>
    <title>Songsmith and The Police</title>
    <link>http://www.kubat.nl/pages/blogaria/130#130</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 There have been enough stories about Microsoft's Songsmith (good
friend Eddie
<a href="http://eddie.niese.net/20090126/omfg-microsoft-songsmith/" target="_blank">wrote
about it too</a>. But the parodies are maybe even worse than the
original Microsoft ad. My favorite is Songsmith's version of Roxanne
(The Police):

<p/>
<center>
<object width="500" height="315"><param name="movie"
value="http://www.youtube.com/v/ypycpKQxXR0&hl=en&fs=1&rel=0&border=1"></param><param
name="allowFullScreen" value="true"></param><param
name="allowscriptaccess" value="always"></param><embed
src="http://www.youtube.com/v/ypycpKQxXR0&hl=en&fs=1&rel=0&border=1"
type="application/x-shockwave-flash" allowscriptaccess="always"
allowfullscreen="true" width="500" height="315"></embed></object>
</center>

<p/>
Is that really a steel drum in that tune? Wow, amazing! It's pure
genius that just by "listening" to the lyrics, Songsmith can predict
that The Police would use steel drums a bit later (in Every Little
Thing).. Simply stunning. Gee, I need to get that program!

 
</description>
   </item>
   <item>
    <title>My own Ministery of Silly Walks</title>
    <link>http://www.kubat.nl/pages/blogaria/129#129</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/SillyWalk-cut.jpg" class="floatleft"/>Sometimes there's no escaping looking stupid on a still frame.
Actually that occurs quite frequently to me.

<p/>Here's a fine example, in full size, my own Ministery of Silly
Walks (or is it, "Beware of that dog pile"?)

 
</description>
   </item>
   <item>
    <title>CoolIris Mini HOWTO</title>
    <link>http://www.kubat.nl/pages/blogaria/128#128</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <h1>A great way to browse pictures</h1>

Yesterday a collegue showed me CoolIris. Whee! What a magnificent way
to browse through pictures or videos! Kudos, guys at CoolIris, and
thanks for showing me, Bas!

<p/> Of course such technology can't go untested. So I tried it out to
see how it works, and... it works really beautifully. If you want to
test it out, here's what you need to do:

<ul>

  <li> You must have Firefox 3. Well, we all have that, right? If not,
  get it at <a href="http://www.mozilla.org/"
  target="_blank">http://www.mozilla.org/</a>. I think it's at the
  moment <b>the</b> browser to have. </li>

  <li> In Firefox, you need to install the addon "Cooliris". If you
  don't have that extension yet, go to the Firefox menu item Tools,
  then Add-ons, and enter Cooliris in the search box. Install the
  add-on and you're all set. </li>

  <li> Next, go to a CoolIris-enabled site. You will see that at the
  right top corner of the Firefox window, there is now a CoolIris
  laucher button. Click it.. and be amazed. </li>

  <li> I've of course also created a small
  sample. <a href="/pages/nasapics">My Nasa pictures 
  collection is CoolIris-enabled, so give it a
  go</a>. (The page takes a while to load, there's just lots of
  pictures there, don't be too impatient.) </li>

</ul>

<h1>Enabling your own site</h1>

Here's how you enable your own photo collection for CoolIris. It's so
radically simple that you'll be amazed.

<ul>

  <li> In the HTML page that presents the index to your pictures
  collection, add the following to the head tag:

    <pre>
      &lt;link rel="alternate"
          type="application/x-cooliris-quick"
          href="/path/to/cooliris-quick.xml"/&gt;</pre>

  The "path/to" is of course a directory specifier that you need to
  change, or remove if you're planning to serve the XML file from the
  current directory.</li>

  <li> In the directory where the above "/path/to" points, 
  create a file "cooliris-quick.xml" which maps thumbnails to the
  big pictures. In my case, a thumbnail picture is
  e.g. <i>/nasa/THUMB-040523cruxa_seip_full.jpg</i>, and the
  corresponding big version is <i>/nasa/040523cruxa_seip_full.jpg</i>.
  So in my case, there's just the "THUMB-" that needs to be taken out to get to
  the big picture. For me, the file "cooliris-quick.xml" looks like:

    <pre>
      &lt;?xml version="1.0" encoding="utf-8" standalone="yes"?&gt;
      &lt;cooliris-quick version="1.0"&gt;
      &lt;src&gt;^(.*)THUMB-(.*)$&lt;/src&gt;
      &lt;dst&gt;{1}{2}&lt;/dst&gt;
      &lt;/cooliris-quick&gt;</pre>

  Notice how the "src" tag uses regular expressions. The "dst" tag
  references regular expressions in parentheses using {1}, {2} and so
  on. Really easy to build. </li>

</ul>

Well, that's about all! Have fun!
 
</description>
   </item>
   <item>
    <title>UDP and DNS balancing</title>
    <link>http://www.kubat.nl/pages/blogaria/127#127</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/bignose2.jpg" class="floatright"/> Based on a couple of ideas
from the <a href="http://xrforum.org" target="_blank">Crossroads
forum</a> and also based on thoughts of my good friend Eddie, I've
crafted a prototype of a UDP balancer. In this case it's hand-crafted
to forward or balance DNS lookups. The description is a bit
lengthy; I parked it in its <a href="/pages/dnsbalancer">separate
page</a>. Enjoy and <a href="mailto:karel@kubat.nl">let me know</a> if
you have questions or remarks!

 
</description>
   </item>
   <item>
    <title>Life in graphs</title>
    <link>http://www.kubat.nl/pages/blogaria/126#126</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Stumbled on this by coincidence. Brilliant or what?

<p/>
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/lWWKBY7gx_0&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/lWWKBY7gx_0&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object> 
</description>
   </item>
   <item>
    <title>Skeined yet?</title>
    <link>http://www.kubat.nl/pages/blogaria/125#125</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/BruceSchneier.png" class="floatright"/>
"Have you skeined yet?" Or maybe it's "Have you been skeined yet?" The
SHA digest algorithm has a contender: Skein (pronouce as: rain, but
with sk). I've no idea if it's any good, but if Bruce Schneier is
co-author of this thingy, then it's going to get loads of exposure. I
wonder how many programs will get a new
flag <code>--use-skein-512</code> in the near future? Plus of course
<code>--pedantic</code> which implies <code>--use-skein-1024</code>?
The paper claims that Skein runs faster than SHA, and the download
includes optimized code for 32 and 64 bit Intel systems. The smallest
Skein-128 is supposedly suitable for very small systems (smartcards).
All written in C, yay. Impressive!

<p/> <a href="http://www.schneier.com/skein.html" target="_blank">Read
more</a> yourself and get the download zip.
 
</description>
   </item>
   <item>
    <title>New Crossroads on the horizon</title>
    <link>http://www.kubat.nl/pages/blogaria/124#124</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 My pet project <a href="http://crossroads.e-tunity.com"
target="_blank">Crossroads</a> (a software load balancer and fail over
utility) is really taking jumps forward. There are countless people to
thank - developers, bench markers, and not in the last place: the
users. Since Crossroads got its forum at <a href="http://xrforum.org"
target="_blank">xrforum.org</a>, the interest has increased and so has
the number of people who actively participate. There have been many
useful and new changes.

<p/> But first, version 2.30 - next stable - is about to come out.
This is basically a (hopefully) bugfree stability release,
with <b>huge</b> optimizations. Preliminary tests show that Crossroads
in both TCP mode and in HTTP mode outperforms comparable balancers!
There ya go.

<p/> But wait, that's not all. The next development version 2.31 is
already in the oven. It's not available as download yet - but will
soon be - so check either the Downloads section
at <a href="http://crossroads.e-tunity.com"
target="_blank">crossroads.e-tunity.com</a> or check the SVN
repository at <i>svn://svn.e-tunity.com/crossroads/trunk</i>. What
does the future hold?

<ul>

  <li>The control script <i>xrctl</i> now relies on an XML
  configuration file, so that all controls have been externalized from
  Crossroads and from its control script.</li> 

  <li>The performance is even better than version 2.30-stable.</li>

  <li>Much more flexible back end checking. The older versions would
  only try to establish a TCP connection to see if a back end is
  alive. Now, checks can be configured to connect to other ports or
  IP's, or they can do a "HTTP get" of e.g. a health check service.
  Or, as a last resort, a user-supplied program is called to do its
  magic and to tell Crossroads how the back end is doing.</li>

  <li>The web interface is greatly enhanced. Its status has been
  steadily increasing from a "nice feature" to a true reporting and
  maintenance tool. All features can be viewed, and almost all
  features can be set. Even new back ends can be added. Currently the
  only things that can't be controlled through the web interface, are
  the balancer server port and the balancing type (tcp or http).</li>

  <li>DNS lookups of back end addresses are cached. This ensures that
  the domain name server isn't hit all the time - and again increases
  performance. </li>

  <li>Denial-of-service (DOS) detection can now call a user supplied
  program to take special measures. The detection of DOS attacks and
  protection inside XR itself was written previously by Gabriel M.,
  but now, e.g. <i>iptables</i> can be invoked to block potential
  trespassers. 

</ul>

Big changes. I can't wait to push out 2.30-stable, so that
2.31-development can be made available as a download too. All in all,
I'm very happy with the direction that Crossroads has taken. The
complete rewrite from the "old" Crossroads-1 code has been worth
while. And of course big thanks go to everyone who's involved - all
testers, contributors, people who come up with ideas, and of course
Rene K., forum master and tireless tester, bughunter, benchmarker, and
what not.

<p/> Since images speak louder than words, here's a snapshot of the
web interface. This balancer runs in HTTP mode, and the image shows
what can be configured for it.

<center>
  <img src="/bld/XR-server.png"/></center>

<p/>
And here's the web interface showing a back end.

<center>
  <img src="/bld/XR-backend.png"/></center>

<p/> 
Interested? Is your curiosity tickled? Get
<a href="http://crossroads.e-tunity.com"
target="_blank">Crossroads</a> and become a member of the
<a href="http://xrforum.org" target="_blank">forum</a>!
 
</description>
   </item>
   <item>
    <title>Thread safe or not</title>
    <link>http://www.kubat.nl/pages/blogaria/123#123</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I was mailing with Rene K., forum master of the
<a href="http://xrforum.org/" target="_blank">Crossroads forum</a>,
co-developer, supporter, and benchmarker of
<a href="http://crossroads.e-tunity.com/"
target="_blank">Crossroads</a>. We got into a discussion of the
thread-safeness of <code>gethostbyname()</code>. (Incidentally.. I
found that Solaris warns that <code>gethostbyname()</code> isn't
thread-safe, while on my Mac it seems to be no problem. Go figure.)

<p/> Anyway, I sent Rene a new source file to try out. It didn't work
out. So he replied with:

<pre>
And that's what you call thread safe.... tssss.. This is thread safe:

struct sockaddr_in backendaddr;
backendaddr.sin_family = AF_INET;
backendaddr.sin_port = htons(bdef.port());

// Who needs name resolution anyway
backendaddr.sin_addr.s_addr = 3540232384;
</pre>

<b>LOLZ!</b>
 
</description>
   </item>
   <item>
    <title>WOW patch 3 on a case sensitive MacOSX filesystem</title>
    <link>http://www.kubat.nl/pages/blogaria/122#122</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/angry.jpg" class="floatleft"/>
Today was Patch Day for WOW. I happily started to download the patch.
Ooh! Glyphs, new talents, a new harbor in Stormwind... my hunter
nerfed, of course.. Couldn't wait to see it all. Everything in
preparation for the upcoming Wrath of the Lich King expansion.

<p/> Then.. BANG! While applying the patch, WOW told me that WotLK
would never ever run on a case-sensitive filesystem. Aargh! When I
installed this Mac, I chose a case-sensitive journaled filesystem on
purpose! It's Unix after all, innit? And Unix's supposed to be
case-sensitive! Files <i>Foo</i> and <i>foo</i> are supposed to be
different!

<p/>
Now this p's me off, totally. Can't the guys at Blizzard get
their file naming schemes in order so that a "File" is a "File",
instead of thinking that it's maybe a "fILE"? After cursing around for
a bit, I decided that I'd have to fix it myself. Not enjoying WOW is
just too cruel to consider.

<p/> So now what? I'm definitely not re-installing my Mac. Not for
this. Furtunately, the following recipy works like a charm: you get to
apply the patch, while keeping your main disk in case-sensitive mode.

<ul>

  <li>
    Create a new disk image using Disk Utility. Use the following
    procedure:

    <ul>
      <li> Fire up the Disk Utility and click New Image. </li>
      
      <li> As for the image name, choose e.g. "WOW" and save it to a
      location that's familiar to you, say your desktop. This goes
      into the "Save as" box.</li>

      <li> For the volume name, use "WOW". </li>

      <li> For the volume size, choose "custom", then enter the size
      as 20Gb. Don't worry, the image won't actually be 20Gb large, it
      will use as much real diskspace as required. The 20Gb means that
      it can grow up to that size.</li>

      <li> For the volume format, go with "Mac OS Extended
      (journaled)". Don't go with case-sensitive, for obvious
      reasons.</li>

      <li> If you like, choose an encryption and a pass phrase. I
      didn't go through this hassle for security reasons, so chose
      just left "no encryption" in this box. </li>

      <li> For partitions, use "Single partition - Apple Partition
      Map".</li>

      <li> For the image format, use "sparse disk image". This is
      important, "sparse" means that unused parts of the image won't
      gobble up your disk. </li>

      <li> Hit "Create".</li>

    </ul>
  </li>

  <li> After you wait a while, your brand new image will be ready for
  usage. You can now either install WOW from scratch to that location,
  or you can copy your existing WOW files (probably in
  "/Applications/World of Warcraft") onto the new image to save time.
  I did the latter.</li>

  <li> If you choose to copy: here's a bit of bad news. You can't just
  rely on Finder to copy the folder "World of Warcraft" from
  "/Applications" into the new image. Why? 'Cuz it'll bomb too, on the
  different handling of filename casing between the source and target
  disks. Aargh! I can imagine that the Finder would pop up a warning
  about this, but just crash... Sigh. Fortunately your Mac is a Unix
  box with all the reliable goodies under the hood. Open a Terminal
  window, and type the magic commands (be sure not to make typo's):

    <pre>
      cd /Volumes/WOW
      (cd /Applications; tar cf - 'World of Warcraft/') | tar xvf -
      exit</pre>
	
  You might need to change "WOW" into whatever name you gave your
  image, and you might need to change "/Applications" into the
  location of your current WOW installation if it differs. But you get
  the idea.</li>

  <li> Once the above "tar" commands finish copying files, open up the
  mounted WOW image in your Finder. Start up the game, let it patch
  itself. It will probably start the patch downloader again - but no
  worries, the downloader will only verify the existing patch file
  and apply the patch. </li>

  <li> Once you've verified that all works, open up "/Applications" in
  your Finder. You can now delete the old folder "World of Warcraft"
  since it's unusable anyway. </li>

</ul>

Good luck, hope that it works for you, if you need it. Incidentally
you can apply the same trick to other "misbehaving" applications that
require a case-insensitive file system...
 
</description>
   </item>
   <item>
    <title>Surprising C++ optimizations</title>
    <link>http://www.kubat.nl/pages/blogaria/121#121</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Over the last few days I've been optimizing my pet load balancer
<a href="http://crossroads.e-tunity.com"
target="_blank">Crossroads</a>. I'm happy to say that the
optimizations have been hugely succesful - a 25% increase in raw TCP
throughput, and an 80% increase in HTTP mode. The optimizations
involved many facets, some of which I had expected, others very surprising.
Here's a surprising one.

<p/> Normally when I write programs - especially daemons, like
Crossroads - I make sure that I implement a layered logging facility. For
example: errors and warnings are always logged, informational messages
only when flag -v is used, and debug messages only when flag -d is
used. Standard approach, right?

<p/> A likely C way to implement this, might be to have
functions <code>errormsg()</code>, <code>warningmsg()</code> and so on.
Inside the "verbose information" function, a flag is inspected to see
whether -v was given on the command line. To illustrate:

<pre>
void verbosemsg(char const *fmt, ...) {
    if (! flag_verbose)
        return;

    .
    . /* Here the message is actually output, e.g. using
    .  * va_start(), vprintf(), va_end()
    .  */
    .
}
</pre>

The calling code simply calls <code>verbosemsg()</code> without regard
to the flag -v. The actual decision whether to output messages is
inside the function. The idea is that the calling code doesn't need to
be cluttered with if-statements to check
whether <code>flag_verbose</code> is on or not. For example, here's
some calling code:

<pre>
/* Example of calling code */
verbosemsg ("Running at PID %d\n", getpid());
</pre>


<p/> So far so good, except that Crossroads isn't a C program, but a
C++ program. So, keeping in mind "good C++ style",
a <code>printf</code>-like approach is a big no-no, right? Ok, let's then
try a true OO-approach. I've illustrated some concepts in the
following code. It's a bit lengthier (because it's a working piece of
code), and defines a helper class <code>msgstring</code>, so that it's
possible to append an integer to a string. The <code>msgstring</code>
is output in class <code>verbosemsg</code>.

<pre>
#include &lt;iostream>
#include &lt;sstream>
#include &lt;string>

using namespace std;

// msgstring is derived from string, to enable "+ int"
// Other appending operators can be added ad lib.
class msgstring: public string {
public:
    // Start with a simple char*
    msgstring(char const *s): string(s) {
    }

    // Or with a string
    msgstring(string const &s): string(s) {
    }

    // Concatenation with an int
    msgstring const &operator+ (int i) {
	ostringstream o;
	o &lt;&lt; i;
	*this += o.str();
	return *this;
    }
};

// for testing:
bool flag_verbose = true;

class verbosemsg {
public:
    // Constructor that outputs info when flag_verbose is true
    verbosemsg (msgstring const &s) {
	if (flag_verbose)
	    cout &lt;&lt; s;
    }
};

// main() to test it all
int main() {
    verbosemsg (msgstring("Hello World!\n"));
    int i = 42;
    verbosemsg (msgstring("The answer is.. ") + i + "\n");
    return 0;
}
</pre>

So far so good. The caller can still say <code>verbosemsg(...)</code>
without having to wrap this in an awkward if-statement. The decision
whether to output a message is made later. Incidentally, in the above
code <code>verbosemsg</code> is a class. It could just as well be a
function, that doesn't matter.

<p/>
<img src="/bld/pickle.jpg" class="floatright"/><b>But here's the catch.</b> When no verbose messages are
generated, then the overhead in the C version is: one call, one if.
The overhead in the C++ version is way bigger: the entire message must
be constructed, overloaded + operators are called to concatenate
information, and that object is passed via reference
to <code>verbosemsg</code>. Only then is the if condition evaluated.
The result? The C++ code is <b>much</b> slower. Really.

<p/>
So now what? It's quite a pickle. I see the following options:

<ul>
  
  <li>
    Populate the C++ code with if-statements that prevent the
    overhead when <code>flag_verbose</code> is false. The evaluation of
    the flag would then not occur inside <code>verbosemsg</code> but in
    the calling code, which might look like:

    <pre>
// main() to test it all
int main() {
    if (flag_verbose)
        verbosemsg (msgstring("Hello World!\n"));

    int i = 42;

    if (flag_verbose)
        verbosemsg (msgstring("The answer is.. ") + i + "\n");

    return 0;
}
    </pre>

    <b>Yech!</b> The whole idea of isolating <code>flag_verbose</code>
    inside <code>verbosemsg</code> was to <i>avoid</i> having
    if-conditions all over the place!
  </li>

  <li>
    Use the plain-old <code>printf()</code> style messaging, such as
    the C function <code>void verbosemsg(char const *fmt, ...)</code>
    that is shown at the top.

    <p/> This isn't OO-ish, it isn't type-safe (though gcc does a fine
    job of warning against a mismatch between the format string and
    remaining arguments), but -- it's fast.
  </li>
    
</ul>

As I see it, this is just another example of the following: "C was
created to be fast. C++ is an addon to make it neat and pretty." Speed
or beauty? It just depends on your situation at hand...

<p/>

<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">Upon reading the above, Eddie wrote me to point out that the
	    construct <i>if(condition) generateoutput(string + string
	    ...)</i> is very common in Java, to make sure that logging
	    doesn't hog up too many resources. He further remarked that
	    it's a shame that Java doesn't have preprocessing. Else,
	    one could wrap the whole thing in a macro.</td></tr></table>

<p/>

Thinking about it: yes, that's pretty usable. It moves the
if-condition into the caller's code without the necessity to type the
if-statement all the time. So here's a quick and dirty illustration of
the concept. May the source be with you.

<pre>
#include &lt;iostream>
#include &lt;sstream>
#include &lt;string>

using namespace std;

/* Class Mstr: derived from string to allow for overloading '+'
 * which handles concatenation of the string with other types
 */
class Mstr: public string {
public:
    Mstr(string s): string(s) {}
    Mstr(char const *s): string(s) {}
    Mstr const &operator+ (int i) {
	ostringstream o;
	o &lt;&lt; i;
	*this += o.str();
	return *this;
    }
};

/* Class Msg: encapsulates the on/off state of the verbose flag,
 * and defines a method msg() that outputs an Mstr. Caller must
 * wrap the msg() call in a if-condition that tests Msg::on().
 */
class Msg {
public:
    static void msg (Mstr const &m) {
	cout &lt;&lt; m;
    }
    static void on(bool o) {
	enabled = o;
    }
    static bool on() {
	return enabled;
    }
private:
    static bool enabled;
};
bool Msg::enabled = false;

/* For easy usage:
 * Macro verbosemsg() handles the if-condition of Msg::on()
 * and optionally calls Msg::msg() to generate output
 */
#define verbosemsg(x) if (Msg::on()) Msg::msg(x)

/* And of course, main() to test it with a couple of
 * verbose statements. */
int main() {
    Msg::on(true);
    
    verbosemsg("Hello World!\n");
    for (int i = 1; i &lt; 5; i++)
	verbosemsg(Mstr("Loop: ") + i + "\n");

    return 0;
}
</pre>

  
 
</description>
   </item>
   <item>
    <title>Weird system message</title>
    <link>http://www.kubat.nl/pages/blogaria/120#120</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/scared.jpg" class="floatleft"/>
Today while monitoring my <i>/var/log/system.log</i> file, I suddenly saw:

<p/>
<code>
Oct 14 18:21:19 Thera SyncServer[17483]: SyncServer: Truth vacuumed. Next vacuum date 2008-10-28 17:21:18 +0100
</code>
<p/>

OMG!

<p/> I immediately shut down my system, and unplugged all electrical
home appliances - especially the vacuum.  

<p/>
<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">Good buddy Eddie wrote me: 'That message comes from
	    sqlite. The SyncServer uses an embedded sqlite database. A
	    few users were complaing that the database grew too large.
	    So nowadays, the SyncServer "vacuums" the database
	    to keep its size within limits.' Hmm.. might be.. but
	    I'm still not turning on my vacuum cleaner.</td></tr></table>
 
</description>
   </item>
   <item>
    <title>Data mining against terrorism does not work</title>
    <link>http://www.kubat.nl/pages/blogaria/119#119</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/phat.jpg" class="floatright"/>
Oh shock! <a href="http://news.cnet.com/8301-13578_3-10059987-38.html"
target="_blank">CNet News</a> reported yesterday that according to a
report by the US National Research Council, "automated identification
of terrorists through data mining or any other mechanism is neither
feasible as an objective nor desirable as a goal of technology
development efforts. Inevitable false positives will result in
ordinary, law-abiding citizens and businesses being incorrectly
flagged as suspects."

<p/> Who would've suspected such a shocking revelation?

<p/>
- <a href="http://www.kubat.nl/pages/blogaria/55">Bayes bites</a> <br/>
- <a href="http://www.kubat.nl/pages/blogaria/93">Datamining is for
  dogs</a> <br/>
- <a href="http://www.kubat.nl/pages/blogaria/102">That myth was
  already busted</a> <br/>
- <a href="http://www.kubat.nl/pages/blogaria/110">Photography won't
  help either</a> <br/>

<p/> Yes indeed, who would've suspected.

 
</description>
   </item>
   <item>
    <title>Crossroads at the top of Freshmeat.net</title>
    <link>http://www.kubat.nl/pages/blogaria/118#118</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I bet every contributor of open source programs has this - but it's
great fun to catch your project at the top of the announce list of
<a href="http://freshmeat.net/" target="_blank">freshmeat.net</a>. I
saw it by accident a few days ago ;-)

<p/>
<center>
  <img src="/bld/XR-Freshmeat-Announcement.png"/></center>
 
</description>
   </item>
   <item>
    <title>Stupid spammers at Computable</title>
    <link>http://www.kubat.nl/pages/blogaria/117#117</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I received "yet-another-user-directed-message" - umm spam. But
this one's different. It's from a renowned Dutch firm that issues an
important magazine for ICT folks, the Computable. Also, what's
different about it, is that it's a pretty stupid mess-up. FUBAR! FAIL!

<p/> Translated: <i>"Dear
%%Sex%%&nbsp;&nbsp;&nbsp;%%Middlename%%&nbsp;&nbsp;&nbsp;%%Lastname%%,
Would you like to ..."</i> And before you ask, the "sex" thing is
presumably supposed to expand into Mr. or Mrs. (no, they aren't THAT
kind of magazine).

<p/>
<center>
  <img src="/bld/ComputableSpam.png"/></center>
<p/>

Guess what. Given this message, I'm totally not interested in their
leads to new business. (Not that I'd been interested otherwise...)
 
</description>
   </item>
   <item>
    <title>Spam prevention with Postfix and Postgrey</title>
    <link>http://www.kubat.nl/pages/blogaria/116#116</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/happy.jpg" class="floatright"/>
Today I got <i>greylisting</i> working on our mailserver. Hooray! The
idea is that when the mail server is contacted to receive mail, it
tells its client: "Come back later." Real e-mail deliver systems will assume
that the mail server is too busy and will indeed retry; but many spam
system (botnets!) will just drop the attempt and move on to the next
e-mail address.

<p/> The configuration that we run uses Postfix as the SMTP daemon,
and Postgrey as a helper. Here's how.

<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">The original blog entry had the configuration
of <i>/etc/postfix/main.cf</i> in the wrong order; the
<i>permit_sasl_authenticated</i> entry should come first. Fixed now
(sept. 8th). Thanks, Peter B.!</td></tr></table>


<h2>Installing Postgrey</h2>

Postgrey can be obtained from <a href="http://postgrey.schweikert.ch/"
target="_blank">http://postgrey.schweikert.ch/</a>. Installation of
the software itself is straight-forward:

<ul>
  <li> Change-dir to a suitable 'sources' directory; </li>
  <li> Unpack the distribution, which comes as an
  archive <i>postgrey-X.YY.tar.gz</i>. X.YY is the version number,
  1.32 at the time of this writing; </li>
  <li> The archive creates a subdirectory <i>postgrey-X.YY</i>, from
  which three files need to be copied to your system directories:</li>
</ul>
<pre>
root$ cp postgrey-X.YY/postgrey /usr/local/sbin
root$ cp postgrey-X.YY/postgrey_whitelist_* /etc/postfix/
</pre>

The executable <i>postgrey</i> which is now in <i>/usr/local/sbin</i>
is a Perl script, and needs a few modules which are installed
using <i>cpan</i>:

<pre>
root$ cpan
cpan> install Net::Server
cpan> install IO::Multiplex
cpan> install BerkeleyDB
cpan> quit
root$
</pre>

<b>Note that</b> the Perl module <i>BerkeleyDB</i> needs the "devel"
version of the Berkeley DB libs. Your system might already have the
libs, but maybe not the developers files such as the headers. On SuSE
the right package is called <i>db-devel</i>. If the <i>cpan</i>
installation of <i>BerkeleyDB</i> fails, then get the developers files
of the right package, and retry <i>cpan</i>.


<h2>Configuring Postgrey</h2>

Before <i>postgrey</i> can be started, the following actions are
necessary:

<pre>
root$ useradd postgrey  
root$ mkdir -p /var/spool/postfix/postgrey
root$ chown postgrey /var/spool/postfix/postgrey
</pre>

Furthermore a startscript must be created, in my case
as <i>/etc/init.d/postgrey</i>. I chose to run Postgrey on local port 6000:

<pre>
#!/bin/sh

case "$1" in
  start)
        /usr/local/sbin/postgrey --inet 127.0.0.1:6000 -d
        ;;
  *)
        echo 'Only startup of postgrey implemented.' 1>&2
        ;;
esac
</pre>

The script is made executable, and is enabled using:

<pre>
root$ chmod +x /etc/init.d/postgrey
root$ chkconfig -a postgrey
</pre>

After that, Postgrey can be started. If all works well, then it should
come up without problems:

<pre>
root$ /etc/init.d/postgrey
</pre>


<h2>Configuring Postfix</h2>

The final step is to tell Postfix that it should consult Postgrey.
This is done in <i>/etc/postfix/main.cf</i>. The line stating
"recipient restrictions" is modified into the following:

<pre>
smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination,
  check_policy_service inet:127.0.0.1:6000,
  permit
</pre>  

After that Postfix can be restarted. I have <i>rcpostfix</i>, your
system may need a different command.

<pre>
rcpostfix restart
</pre>


<h2>Verifying that it works</h2>

You can see effects when examining <i>/var/log/mail</i> (or your
system-dependent mailer log file). For example the IP address (in this
case it's even spam), 93.172.120.224 is trying to deliver mail:

<pre>
connect from 93-172-120-224.bb.netvision.net.il[93.172.120.224]
action=greylist, reason=new, client_name=93-172-120-224.bb.netvision.net.il,
  client_address=93.172.120.224, sender=linreisachermet@reisacher.de,
  recipient=info@e-tunity.com 
NOQUEUE: reject: RCPT from 93-172-120-224.bb.netvision.net.il[93.172.120.224]:
  450 &lt;info@e-tunity.com>: Recipient address rejected: Greylisted, see
  http://postgrey.schweikert.ch/help/e-tunity.com.html;
  from=&lt;linreisachermet@reisacher.de> to=&lt;info@e-tunity.com>
  proto=ESMTP helo=&lt;93-172-120-224.bb.netvision.net.il>
lost connection after DATA from 93-172-120-224.bb.netvision.net.il
  [93.172.120.224]
disconnect from 93-172-120-224.bb.netvision.net.il[93.172.120.224]
</pre>

This guy hung up the phone and won't be back. Just to show that real
mail gets through, here's an example of that too. It's the second try
that IP 209.85.134.191 connects, and this time it's allowed to deliver
its message:

<pre>
connect from mu-out-0910.google.com[209.85.134.191]
action=pass, reason=triplet found, delay=1699,
  client_name=mu-out-0910.google.com, client_address=209.85.134.191,
  sender=karel@kubat.nl, recipient=karel@e-tunity.com 
client=mu-out-0910.google.com[209.85.134.191]
message-id=&lt;7a5a1ed10809061230w23cadcc4l229ec55f06a3e688@mail.gmail.com>
37C6A287FF: from=&lt;karel@kubat.nl>, size=2411, nrcpt=1 (queue active)
</pre>

There's of course a small downside to this approach. Your mail will
arrive somewhat later, since it requires two attempts to deliver it.
But the upside is huge; spam really drops!

Have fun!
 
</description>
   </item>
   <item>
    <title>The Gnomish Flying Machine</title>
    <link>http://www.kubat.nl/pages/blogaria/115#115</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/FlyingMachine.jpeg" class="floatleft"/>
Today good buddy Ed let me sent me a message. <i>"Yesterday I finally had
enough rep to get a Seaforium Charge Schematic. I needed that for my
flying machine, and incidentally it also blows up doors, locks and
lockboxes."</i> He sent me the accompanying picture.

<p/> This of course applies to the virtual World of Warcraft. Virtual
Ed is <a href="http://www.kubat.nl/pages/blogaria/103#103">know to
walk around holding a fish</a>, and is a Gnomish Engineer. They can
build sooo cool stuff! Not that it works perfectly though. Ed:
<i>"Sometimes it malfunctions (like all Gnome engineering crap). You
don't fall out of the sky, but the engine dies and has to restart. It
doesn't kill you, but reminds you that what you're crafting, is
malfunctioning crap."</i>

<p/> I'm sooo jealous! Ah well. Ed, at least in a duel my hunter p0wns your
warrior (for now....)
 
</description>
   </item>
   <item>
    <title>Bank customer data on eBay</title>
    <link>http://www.kubat.nl/pages/blogaria/114#114</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/rbs-logo.gif" class="floatright"/>
It's getting boring: Every day the similar newsflashes about data
loss. Here we go again.

<p/>
Though <a href="http://www.kubat.nl/pages/blogaria/112#112">Big
Brother is stupid</a>, Little Brothers can be pretty thick too.
Today, the <a href="http://news.bbc.co.uk/2/hi/uk_news/7581540.stm"
target="_blank">BBC</a> reported that a computer that was offered on
eBay, had data on its hard disk concerning a few million customers,
their account details, signatures, phone numbers, and the mothers'
maiden names. It was a 1U server with 345 CD back ups, with data
concerning credit card applications. The guy who'd bought the server
had to replace a memory chip and presto, it booted and worked.

Looks to me like someone worked in the datacenter and decided not to
wipe the drives of a server, since it appeared faulty anyway. There's
just one failsafe way of wiping drives before you throw them away, and
this method involves power tools. Really.

<p/> Most data are related to the Royal Bank of Scotland.
Apparently their slogan is "make it happen" (I'm not joking).
I could list a million things they should've done, or not done,
and how the guilty should be held responsible. But it would be just
too depressing to rehash this.
 
</description>
   </item>
   <item>
    <title>Mutexes in C++ Threads</title>
    <link>http://www.kubat.nl/pages/blogaria/113#113</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Some time ago I wrote about <a href="http://www.kubat.nl/pages/blogaria/107#107">Posix threads in C++</a>. At that time I "promised" that there would be an update on mutex locks. Here it is.

<p/> This code is -as far as locks are concerned- literally what Frank B. sent me after my original blog entry. I'm showing it here as-is, because it's just neat, and looks good. As ever, <a href="mailto:karel@kubat.nl">drop me a note</a> if you have remarks or questions! Summarizing, the <b>big</b> difference is that the locking is now much more fine-grained. The caller supplies to <i>lock()</i> a pointer to a (global or static) variable that he's about to access; and a corresponding mutex is locked that applies <i>only to that variable</i>. Other threads might have a lock on a totally different global or static variable. So, a caller that's interested in writing something to <i>cout</i> (such as in this example) would code something like:

<pre>
/* Sample of how to use lock() / unlock().
 * This won't hamper another thread that goes:
 *   lock(&cerr); cerr &lt;&lt; "Some text\n"; unlock(&cerr);
 * because locks are kept separate for cout and cerr.
 */ 
lock(&cout);
cout &lt;&lt; "Here's my message.\n";
unlock(&cout);
</pre>

In contrast, the <a href="http://www.kubat.nl/pages/blogaria/107#107">old post </a> has just one global mutex, and whoever locks it, has it.

<p/> So below is a full listing of a working program (you can also <a href="/threads/threads1.cc">download</a> it). In comparison to the previous blog entry, just check out <i>Thread::lock()</i> and <i>Thread::unlock()</i>. 

<pre>
/* **************************************************************************
 * threads1.cc - Demo of a C++ Thread Class / [KK 2008-08-26] 
 * Compile using 	c++ -Wall -o threads1 threads1.cc -lpthread
 * then run with	./threads1
 * **************************************************************************/

/* Part 1: Thread class */
#include &lt;errno.h>
#include &lt;pthread.h>
#include &lt;string.h>

#include &lt;iostream>
#include &lt;string>
#include &lt;map>

using namespace std;

class Thread {
public:
    virtual ~Thread();				// dtor

    virtual void act() = 0;			// Pure virtual act()

    pthread_t run(bool joinable = true);	// The starter

    void lock(void *target);			// Synchronization
    void unlock(void *target);

private:
    static void *start(Thread *obj);
    void plock(void *target);

    static bool initialized;			// Mutex initialized yet?
    static std::map&lt;void *,  pthread_mutex_t> 
        s_lock;					// The mutexes database
    typedef std::map&lt;void *,  pthread_mutex_t>::iterator mapIterator;
};

bool Thread::initialized = false;
std::map&lt;void *,  pthread_mutex_t> Thread::s_lock;

Thread::~Thread() {
}

void Thread::lock(void *target) {
    plock(&s_lock);
    plock(target);
    unlock(&s_lock);
}

void Thread::plock(void *target) {
    mapIterator iter = s_lock.find(target);
    if (iter == s_lock.end()) {
	// No such lock yet, create the mutex
        if (int res = pthread_mutex_init(&s_lock[target], 0))
            throw static_cast&lt;string>("Failed to initialize static mutex: ") +
	    strerror(res);
    }
    
    if (int res = pthread_mutex_lock(&s_lock[target]))
        throw static_cast&lt;string>("Failed to obtain mutex lock: ") +
	strerror(res);
}

void Thread::unlock(void *target) {
    if (int res = pthread_mutex_unlock(&s_lock[target]))
        throw static_cast&lt;string>("Failed to release mutex lock: ") +
	strerror(res);
}

pthread_t Thread::run(bool joinable) {
    pthread_attr_t attr;
    pthread_t th;
    int res;

    if (pthread_attr_init (&attr))
	throw ("Cannot initialize thread attributes");
    if (joinable) {
	if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE))
	    throw ("Cannot set thread state as joinable");
    } else {
	if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
	    throw ("Cannot set thread state as detached");
    }
    for (int i = 0; i &lt; 3; i++) {
	res = pthread_create(&th, &attr,
			     reinterpret_cast&lt;void *(*)(void *)>(start),
			     this);
	if (!res) {
	    pthread_attr_destroy(&attr);
	    return (th);
	}
	if (res == EAGAIN) {
	    cout &lt;&lt; "Failed to start thread: " &lt;&lt; strerror(res) &lt;&lt;
		", retrying\n";
	    sleep(1);
	    continue;
	}
	pthread_attr_destroy (&attr);
	throw (static_cast&lt;string>("Failed to start thread: ") +
	       strerror(res));
    }
    
    throw ("Failed to start thread: "
	   "Resources unavailable after 3 tries, giving up");
}

void *Thread::start(Thread *t) {
    try {
	t->act();
    } catch (string s) {
	cerr &lt;&lt; s &lt;&lt; "\n";
    } catch (...) {
	cerr &lt;&lt; "Thread threw an exception\n";
    }

    delete (t);
    return 0;
}


/* Part 2: Example of a Thread-derived class */
class MyThread: public Thread {
public:
    void act();
};

void MyThread::act() {
    for (int i = 0; i &lt; 10; i++) {
	lock(&cout);
	cout &lt;&lt; "Hello World from thread " &lt;&lt; hex &lt;&lt; pthread_self()
	     &lt;&lt; ", counter is " &lt;&lt; i &lt;&lt; "\n";
	unlock(&cout);
	sleep (1);
    }
}

/* Part 3: A tester. Function test1() shows non-joinable threads. 
 * Function test2() shows joinable ones. And of course main() runs it.
 */
void test1() {
    cout &lt;&lt; "Starting two threads,\n"
	 &lt;&lt; "and sleeping for 15 seconds to allow threads to finish.\n";
    
    // Instantiate two thread objects and fire them up.
    (new MyThread())->run(false);
    (new MyThread())->run(false);

    // Wait for the threads to finish.
    sleep (15);
}

void test2() {
    cout &lt;&lt; "Starting two threads,\n"
	 &lt;&lt; "and waiting for them to finish.\n";
    
    // Instantiate two thread objects.
    MyThread
	*a = new MyThread(),
	*b = new MyThread();

    // Start 'em up.
    pthread_t id_a = a->run();
    pthread_t id_b = b->run();

    // Wait for the threads to finish.
    pthread_join (id_a, 0);
    pthread_join (id_b, 0);
}

int main() {
    test1();
    test2();
    return (0);
}
</pre> 
</description>
   </item>
   <item>
    <title>4M dataloss in the UK last year</title>
    <link>http://www.kubat.nl/pages/blogaria/112#112</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/GeorgeOrwell.jpg" class="floatright"/>
Today, <a href="http://www.computerworld.com.au/index.php/id;50110485"
target="_blank">ComputerWorld</a> reports that the UK government lost
4.000.000 personal data records last year. We all saw this coming,
probably. There are enough examples of the
<a href="http://www.kubat.nl/pages/blogaria/93#93">ineffectiveness</a>
of huge data collections, of a general trend of 
<a href="http://www.kubat.nl/pages/blogaria/63#63">downplaying</a> the
importance of security around privacy,
and <a href="http://www.kubat.nl/pages/blogaria/56#56">lax
security</a> around the involved data. In short, of total stupidity in
the Land of the Big Brother.

<p/> Bottom line is, Big Brother is indeed watching the Brittons. That
fact won't be easily reversed. But he's also a total moron. That isn't
easily reversible either.
 
</description>
   </item>
   <item>
    <title>Dropping spam with Postfix and Spamassassin</title>
    <link>http://www.kubat.nl/pages/blogaria/111#111</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/spam.jpg" class="floatright"/>
At e-tunity we were installing a new mail server. So once again, I started
installing Spamassassin to filter out our incoming spam. This time, I
decided to write it up - I bet this isn't the last time that I'll be
doing this.

<p/> This article describes the general setup that 'we' like to use.
What happens with the incoming mail is, that it gets scanned by
Spamassassin. If the mail is not-spam, or 'ham', then of course it
gets delivered to the recipient. If it is spam, then it's parked in a
"spool" directory, but not delivered. We have this setup so that
accidentally spam-marked messages can be found. However, that happens
so rarely - if ever - that we prefer to simply spam, so that
mail readers don't have to process it.

<p/> I'm assuming that the following ingredients are present at the
start:

<ul>
  <li>
    A working Postfix installation, that can accept mail and deliver
    it to users.
  </li>
  
  <li>
    A working SpamAssassin installation, with <i>spamc</i> available,
    and <i>spamd</i> running.
  </li>
</ul>

So here are the necessary actions once the above requirements are met.
The commands shown below are focused on SuSE Linux, so you may have to use
a slightly different syntax, where applicable.


<h2> Creating a user "spamfilter"</h2>

The filtering will be done by a user "spamfilter", so we create it:

<pre>
root: useradd -d /home/spamfilter -m spamfilter
</pre>


<h2> Spooling and Filtering</h2>

All spooling of mail messages and filtering is done by this user
"spamfilter". Here's how. First two directories are created, "bin" and
"spool" in the user area:

<pre>
root: su - spamfilter
spamfilter: mkdir bin spool
</pre>

Next, the script <a href="/spamfilter"
target="_blank">"spamfilter"</a> is placed in the "bin" directory.
This script will later on be called from Postfix to "filter" any mail.
The script collects the mail into a spool file, runs "spamc" to see if
it's ham or spam, and then decides what to do with it. If it's spam,
then the message is left in the spool file. If it's ham, then
"spamfilter" starts Sendmail to deliver it. For reference, the script
is shown below. When installing, make sure that the configuration
section (at the top of the script) is right.

<pre>
#!/usr/bin/perl

use strict;
use Time::HiRes qw(gettimeofday);

# Configuration ---------------------------------------------------------
my $sendmail = '/usr/lib/sendmail';
my $spamc = '/usr/bin/spamc';
my $spooldir = '/home/spamfilter/spool';
my $user = 'spamfilter';
# Configuration ends ----------------------------------------------------

# About to receive a message. Collect it into a spool file.
my ($sec, $usec) = gettimeofday();
my ($s, $m, $h, $dd, $mm, $yy) = localtime($sec);
my $stamp = sprintf("%4.4d-%2.2d-%2.2d:%2.2d-%2.2d-%2.2d.%3.3d",
		    $yy + 1900, $mm + 1, $dd,
		    $h, $m, $s, ($usec / 1000));
my $spoolf = "$spooldir/$stamp";
open (my $of, "&gt;$spoolf")
  or die ("$0: cannot write spool file '$spoolf': $!\n");
while (my $line = &lt;STDIN&gt;) {
    print $of ($line);
}
close ($of) or die ("$0: write failed to '$spoolf': $!\n");

# Run it thru spamc to see if it's ham or spam.
open (my $if, "$spamc -r -u $user &lt; $spoolf |")
  or die ("$0: cannot run '$spamc': $!\n");
my $result = &lt;$if&gt;;
close ($if) or die ("$0: '$spamc' failed\n");
if ($result ne '') {
    # It's spam. Leave in the spool.
    exit (0);
} else {
    # It's ham. Make sure sendmail delivers it.
    system ("$sendmail @ARGV &lt; $spoolf")
      and die ("$0: '$sendmail @ARGV' failed\n");
    unlink ($spoolf)
      or die ("$0: cannot unlink '$spoolf': $!\n");
}
</pre>
    
Once the script is in spamfilter's "bin" directory, it must be made
executable. 

<pre>
spamfilter: chmod +x /home/spamfilter/bin/spamfilter
</pre>

User "spamfilter" needs one more thing. As spam arrives, the spool
directory will slowly be filled. We choose to keep spam around for 30
days, then to delete it. So we start editing the "crontab":

<pre>
spamfilter: crontab -e
</pre>

In the crontab that we're editing now, we put:

<pre>
0 2 * * * find /home/spamfilter/spool -maxdepth 1 -type f -mtime +30 -exec rm -f {} \; >/dev/null
</pre>  

Then we're done with this user:
<pre>
spamfilter: exit
root:
</pre>


<h2>Postfix configuration</h2>

Next, postfix must be informed that incoming mail must be filtered
using the script <i>/home/spamfilter/bin/spamfilter</i>. This is done
in Postfix' configuration file <i>master.cf</i>, often located in <i>/etc/postfix/</i>.

<p/> Near the top, the "smtp" service rule is changed from

<pre>
smtp    inet  n       -       n       -       -       smtpd
</pre>

to

<pre>
#smtp   inet  n       -       n       -       -       smtpd
smtp    inet  n       -       n       -       -       smtpd
  -o content_filter=spamfilter:dummy
</pre>  

Next, the "spamfilter" action is defined in the Interfaces section
of <i>master.cf</i>. The following can be appended to the file:

<pre>
spamfilter unix  -      n       n       -       -       pipe
  flags=Rq user=spamfilter argv=/home/spamfilter/bin/spamfilter -f ${sender} -- ${recipient}
</pre>

Finally, Postfix is restarted:

<pre>
root: rcpostfix restart
</pre>


<h2>Optional: Making Spamassassin stricter</h2>

The default spam threshold of 5 seems a bit lax. I like to be more
restrictive. Using trial and error I found that a threshold value 3.4
works fine. This can be configured
in <i>/usr/share/spamassassin/10_misc.cf</i>:

<pre>
required_score           3.4
</pre>


<h2>Testing it</h2>

All should now work. Try sending yourself a mail. Or try sending
yourself some spam, it should end up in a file
in <i>/home/spamfilter/spool</i>.
 
</description>
   </item>
   <item>
    <title>Bayes and the War on Photography</title>
    <link>http://www.kubat.nl/pages/blogaria/110#110</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/NoPhotography.jpg" class="floatright"/>
In the July episode of Bruce Schneier's Security Blog I found an
interesting article on the
<a href="http://www.schneier.com/blog/archives/2008/06/the_war_on_phot.html"
target="_blank">War against Photography.</a>. Mr. Schneier
writes:
<i>
  "Since 9/11, there has been an increasing war on
  photography. Photographers have been harassed, questioned, detained,
  arrested or worse, and declared to be unwelcome. We've been
  repeatedly told to watch out for photographers, especially
  suspicious ones. Clearly any terrorist is going to first photograph
  his target, so vigilance is required. 

  Except that it's nonsense. The 9/11 terrorists didn't photograph
  anything. Nor did the London transport bombers, the Madrid subway
  bombers, or the liquid bombers arrested in 2006. Timothy McVeigh
  didn't photograph the Oklahoma City Federal Building. The Unabomber
  didn't photograph anything; neither did shoe-bomber Richard Reid.
  Photographs aren't being found amongst the papers of Palestinian
  suicide bombers. The IRA wasn't known for its photography. Even
  those manufactured terrorist plots that the US government likes to
  talk about -- the Ft. Dix terrorists, the JFK airport bombers, the
  Miami 7, the Lackawanna 6 -- no photography."
</i>

<p/> To this I'd like to add that Bayes agrees with Schneier. For the
sake of the argument, let's assume that:
<ul>
  <li>
    The European Union hosts some 500 million people. (The number
    may be a bit off - it also depends on what countries you count.) Let's
    further assume that 1000 of these inhabitants are active terrorists.
  </li>
  <li>
    Let's further assume that half of the non-terrorist inhabitants shoot
    a photo once in a while.
  </li>
  <li>
    To make the argment stand out even more, let's assume
    that <b>almost all</b> terrorists shoot pictures of their next
    bombing target -- even though Schneier reports otherwise. For
    example, let's say that of those 1000 terrorist, only one <i>does not</i>
    take pictures of his next target.
  </li>
</ul>

<p/> The numbers are then as follows:

<center>
  <table>
    <tr>
      <td bgcolor="gray"></td>
      <td bgcolor="gray">Is a photographer</td>
      <td bgcolor="gray">Is not a photographer</td>
      <td bgcolor="gray">Totals</td>
    </tr>
    <tr>
      <td bgcolor="gray">Is not a terrorist</td>
      <td bgcolor="lightgray" align="right">249.999.500</td>
      <td bgcolor="lightgray" align="right">249.999.500</td>
      <td bgcolor="lightgray" align="right">499.999.000</td>
    </tr>
    <tr>
      <td bgcolor="gray">Is a terrorist</td>
      <td bgcolor="lightgray" align="right">999</td>
      <td bgcolor="lightgray" align="right">1</td>
      <td bgcolor="lightgray" align="right">1.000</td>
    </tr>
    <tr>
      <td bgcolor="gray">Totals</td>
      <td bgcolor="lightgray" align="right">250.000.499</td>
      <td bgcolor="lightgray" align="right">249.999.501</td>
      <td bgcolor="lightgray" align="right">500.000.000</td>
    </tr>
  </table>
</center>

<p/> Ok, now here's where Bayes kicks in. It's true that (in this
example) most terrorists are photographers. If you see a terrorist,
then there's a 999/1000 chance that he's a photographer - or 99.9%.
But that's not what we're interested in, is it? Here's the obvious
catch. If you see a photographer, then there's only a 0.000399599%
chance that he's a terrorist - it's 999/250.000.499.

<p/> Bayes concurs: vigilance towards photographers is utter nonsence and
a waste of money and time. <p/> I wrote about Bayesian
statistics <a href="/pages/blogaria/55#55">before</a>. It's just so
unfortunate that so many people believe that because a cow is an
animal, all animals must be cows...

 
</description>
   </item>
   <item>
    <title>Good marital advice</title>
    <link>http://www.kubat.nl/pages/blogaria/109#109</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today the following picture appeared on <a href="http://failblog.org"
target="_blank">failblog.org</a>. I've seen it before, it's an "oldie
goldie", but really brilliant. Enjoy.

<p/>

<center>
  <img src="/bld/fail-owned-advice-fail.jpg"/></center>
 
</description>
   </item>
   <item>
    <title>Squid proxy for personal usage</title>
    <link>http://www.kubat.nl/pages/blogaria/108#108</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/k/watch1.jpg" class="floatleft"/>
Lately I've been reconfiguring my local Squid proxy for more "personal
usage". Meaning that I don't need my Squid instance to keep a long
history of logs, and that I don't need it to keep its cache of HTTP
objects between reboots. Basically, I don't want it to "pollute" my
hard disk - I consider all Squid data as more or less "transient".

<p/> I had to fiddle 'round the configuration file a bit until I got
it right. Here are the changes to the default
configuration <i>squid.conf</i>. (Basically I'm blogging it here, 'cuz
I want a safe place where it's stored, so I don't have to re-invent it
the next time.) It works, when all below changes are applied
to <i>squid.conf</i>, and all mentioned transient data are put in <i>/tmp</i>.

<p/> <b>Warning:</b> Don't use this configuration on a true multi-user
system. The configuration is too "lax" for at, and the download
history can be viewed by all users of the system. But it's ok for a
single-user setup. I don't snoop around in my own download history,
and my firewall prevents unauthorized network connections anyway.

<h2>Changes to the default squid.conf</h2>

<ul>

  <li>
    Access control to requests: this defines networks and proxy-able
    ports and methods.

    <pre>
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http
acl CONNECT method CONNECT
    </pre>
  </li>

  <li>
    HTTP access rules: Who's allowed to access the proxy?

    <pre>
http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access deny to_localhost
http_access allow localhost
http_access deny all
icp_access allow all
    </pre>
  </li>

  <li> 
    Log file locations, coredumps, and the PID file: I've reset these
    all to <i>/tmp</i>. 

    <pre>
access_log /tmp/squid-access.log squid
cache_log /tmp/squid-cache.log
cache_store_log /tmp/squid-store.log
pid_filename /tmp/squid.pid
coredump_dir /tmp
    </pre>
  </li>

  <li>
    The cache directory location: Also set to point to <i>/tmp</i>.

    <pre>
cache_dir ufs /tmp/squid-cache 100 16 256
    </pre>
  </li>

  <li>
    Miscellaneous changes to the default configuration: These are the
    "run user" and the hostname.

    <pre>
cache_effective_user <i>enter-a-user</i>
visible_hostname <i>enter-your-hostname</i>
    </pre>
  </li>
</ul>

<h2>A handy start script</h2>

The following script <i>restart-squid</i> will either fire it up, or
restart it.

<pre>
#!/bin/sh

squid -k interrupt

rm -rf /tmp/squid.pid || exit 1
mkdir -p /tmp/squid-cache || exit 1
chmod 777 /tmp/squid-cache || exit 1
squid -z || exit 1
squid -D || exit 1
</pre>
 
</description>
   </item>
   <item>
    <title>Posix threads in C++</title>
    <link>http://www.kubat.nl/pages/blogaria/107#107</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 A short while ago I rewrote my load balancer
<a href="http://crossroads.e-tunity.com"
target="_blank">Crossroads</a> to a multi-threaded daemon in C++. I
tried to find a neat and elegant way to handle POSIX threads in C++.
Here's what I came up with; feel free to tinker around with it, and if
you have suggestions or
improvements, <a href="mailto:karel@kubat.nl">let me know</a>!

<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">I received a very good review from good friend and
former collegue Frank B., and I've taken most of his comments at
heart. So here's "Version 2". At this time we're still mailing about
the approach, and the (non)elegant parts in it. I'll keep you
posted.</td></tr></table>
<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">I furthermore received comments from Lisa R.,
which identified a race condition in my original code. Fixed now -
thanks Lisa!</td></tr></table>
<table width="100%">
               <tr><td valign="top"><img src="/bld/warning.png"/></td><td valign="top">Also from Frank, I got very neat code for mutex
handling. The code below uses one global variable for locking; Frank's
code is way smarter. Check out the new version at the blog entry
<a href="http://www.kubat.nl/pages/blogaria/113#113">Mutexes in C++
  Threads</a>.</td></tr></table>

<p/> If you want to download the code, get the source file <a
href="/threads/threads.cc">threads.cc</a>. It has all the necessary code
in one file.


<h2>General approach</h2>

I designed a pure virtual class, aptly named <i>Thread</i>, which does
all the work for you and hides the gory details. The
class <i>Thread</i> has a pure virtual member <i>act()</i>, which of
course must be implemented to do something useful.

<p/> The class implements the following member functions:

<ul>	

  <li>
    A virtual destructor, incase derived classes want to implement
    their own.
  </li>

  <li>
    A member function <i>lock()</i> and <i>unlock()</i>, to "synchronize"
    thread execution.
  </li>
  
  <li>
    And finally, there's member function <i>run()</i>, which is called
    to start thread execution. This function returns an ID (of type
    a <i>pthread_t</i>), so that the starter of the thread can wait
    for the thread to finish, if they wish so.
  </li>
</ul>


<h2>A sample MyThread class</h2>

Nothing's complete without a Hello World example. So there we go.
Before diving into what <i>Thread</i> is supposed to look like, here's
how it's used in a derived class.

Each <i>Thread</i>-derived class <b>must</b> implement <i>act()</i>.
and it <b>may</b> implement a constructor, destructor or any other
method it wants. So here's <i>MyThread</i>:

<pre>
class MyThread: public Thread {
public:
    void act();
};

void MyThread::act() {
    for (int i = 0; i &lt; 10; i++) {
	lock();
	cout &lt;&lt; "Hello World from thread " &lt;&lt; hex &lt;&lt; pthread_self()
	     &lt;&lt; ", counter is " &lt;&lt; i &lt;&lt; "\n";
	unlock();
	sleep (1);
    }
}
</pre>

The sample class of course implements <i>act()</i> to do whatever's
necessary. Note that inside <i>act()</i> locks are used to
"protect" <i>cout</i>. In threads, all access to globals or statics
must be protected by locking. If <i>act()</i> wouldn't do this, then
the output from several <i>MyThread</i> runs would get garbled. The
standard POSIX function <i>pthread_self()</i> is used to display the
thread ID inside <i>act()</i>.

<p/> According to Frank's remarks: I have to admit that <i>lock()</i>
and <i>unlock()</i> don't really belong into the <i>Thread</i> class.
A separate class <i>Mutex</i> is in real life more appropriate. Please
consider my squeezing the locks into <i>Thread</i> as laziness... or
"the demo effect"...


<h2>How to start MyThread</h2>

Here's how a <i>Thread</i>-derived class is "started". <u>The caller must
allocate new objects using <i>new</i></u> and then call the <i>run()</i>
method to fire it up. That starts the thread, dissociates it from
the main program, and calls <i>act()</i> to do whatever is supposed to
be done.

<p/> <u>The caller mustn't <i>delete</i> the thread objects!</u> That is
handled entirely within the <i>Thread</i> class. The reason is of
course that the threads run separately - the caller doesn't know the right
timing to call <i>delete</i>.

<p/>(Actually, POSIX threads have a way of "waiting" for a thread to
terminate, using <i>pthread_join()</i>. The caller is of course at
liberty to use this approach. However, I still chose to implement
deallocation entirely within <i>Thread</i>, so that the caller doesn't
need to worry. The caller can just "fire and forget". According to
Frank, this breaks the rule of thumb "if you pack it in, pack it out
yourself". I agree, normally I'd want the one to allocate something to
also de-allocate it. This situation breaks that rule...)

<p/> Here's the first example. The following <i>main()</i> function
fires up two threads, waits 15 seconds, and stops. The necessary waiting
is there to let the two threads finish:

<pre>
void test1() {
    cout &lt;&lt; "Starting two threads,\n"
	 &lt;&lt; "and sleeping for 15 seconds to allow threads to finish.\n";
    
    // Instantiate two thread objects and fire them up.
    (new MyThread())->run();
    (new MyThread())->run();

    // Wait for the threads to finish.
    sleep (15);
}
</pre>

<p/> Here's the second example. This invocation actually waits for the
threads to finish. It involves <i>pthread_join()</i> and is of course
more precise than sleeping for 15 seconds.

<pre>
void test2() {
    cout &lt;&lt; "Starting two threads,\n"
	 &lt;&lt; "and waiting for them to finish.\n";
    
    // Instantiate two thread objects.
    MyThread
	*a = new MyThread(),
	*b = new MyThread();

    // Start 'em up.
    pthread_t id_a = a->run();
    pthread_t id_b = b->run();

    // Wait for the threads to finish.
    pthread_join (id_a, 0);
    pthread_join (id_b, 0);
}
</pre>


<h2>Class Thread</h2>

Finally, here's the class <i>Thread</i> itself. First the class
declaration:

<pre>
class Thread {
public:
    virtual ~Thread();				// dtor

    virtual void act() = 0;			// Pure virtual act()

    pthread_t run(bool joinable = true);	// The starter

    void lock();				// Synchronization
    void unlock();
    
private:
    static void *start(void *obj);

    static bool initialized;			// Mutex initialized yet?
    static pthread_mutex_t thread_mutex;	// Mutex itself
};
</pre>


<h2>Trivial Thread member functions</h2>
    
The constructor and destructor are pretty trivial. The purpose of the
destructor is only to provide a dummy; the constructor initializes the
static data member <i>thread_mutex</i> unless this was already done before.

<pre>
pthread_mutex_t Thread::thread_mutex;
bool Thread::initialized = false;

Thread::~Thread() {
}
</pre>

The members <i>lock()</i> and <i>unlock()</i> use the normal pthread
mutex functions, so that's easy too:

<pre>
void Thread::lock() {
    int res;
    
    if (! initialized) {
	if ( (res = pthread_mutex_init (&thread_mutex, 0)) )
	    throw (static_cast&lt;string>("Failed to initialize static mutex: ") +
		   strerror(res));
	initialized = true;
    }
    if ( (res = pthread_mutex_lock (&thread_mutex)) )
	throw (static_cast&lt;string>("Failed to obtain mutex lock: ") +
	       strerror(res));
}

void Thread::unlock() {
    int res;
    if ( (res = pthread_mutex_unlock (&thread_mutex)) )
	throw (static_cast&lt;string>("Failed to release mutex lock: ") +
	       strerror(res));
}
</pre>



<h2>Thread::run() and Thread::start()</h2>

And now for the member functions that actually starts a
thread, <i>run()</i> and <i>start()</i>. The "tour te force".

<p/> POSIX threads are started using <i>pthread_create()</i>. This C
function requires a "thread entry point", which is a pointer to a
function that accepts a <i>void*</i> argument, and returns
a <i>void*</i>. That's actually the reason that <i>Thread::start()</i>
is there, it converts to the right prototype and it's static, hence
"object-less".

<p/> So first, there's <i>Thread::run()</i>. It has an optional
argument <i>bool joinable</i>, default <i>true</i>, which sets the
thread's "detach state". The caller can choose to start the threads as
either totally detached, or not. When threads are started in detached
mode, i.e., not-joinable, then the caller cannot
use <i>pthread_join()</i> to wait for a thread to finish.

<p/> To be more precise, detached or joinable threads each have
advantages and disadvantages:

<ul>
  
  <li>
    When threads are started as joinable, then the caller can wait for
    them to finish. However, the caller will then have to "remember"
    what threads were started. These are the ID's returned
    by <i>run()</i> when starting the threads.
  </li>

  <li>
    In my experiments, joinable threads ate more resources. Repetitive calls
    to <i>pthread_create()</i> would fail. Detached threads didn't; it
    seems that you can have more of these. But then, joining detached
    threads isn't possible.
  </li>

</ul>

<p/> Oh, just one more thing. When a thread is started, then
error <i>EAGAIN</i> can be the result. In that case, there are no
resources to start the thread at this time. When this happens, <i>run()</i>
will wait a second and retry. If this fails three times in a row,
then <i>run()</i> gives up.

<pre>  
pthread_t Thread::run(bool joinable) {
    pthread_attr_t attr;
    int res;
    pthread_t th;

    if (pthread_attr_init (&attr))
	throw ("Cannot initialize thread attributes");
    if (joinable) {
	if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE))
	    throw ("Cannot set thread state as joinable");
    } else {
	if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
	    throw ("Cannot set thread state as detached");
    }
    for (int i = 0; i &lt; 3; i++) {
	res = pthread_create(&th, &attr,
			     reinterpret_cast&lt;void *(*)(void *)>(start),
			     this);
	if (!res) {
	    pthread_attr_destroy(&attr);
	    return (th);
	}
	if (res == EAGAIN) {
	    cout &lt;&lt; "Failed to start thread: " &lt;&lt; strerror(res) &lt;&lt;
		", retrying\n";
	    sleep(1);
	    continue;
	}
	pthread_attr_destroy (&attr);
	throw (static_cast&lt;string>("Failed to start thread: ") +
	       strerror(res));
    }
    
    throw ("Failed to start thread: "
	   "Resources unavailable after 3 tries, giving up");
}
</pre>

And now <i>Thread::start()</i>. This function receives the <i>this</i>
pointer as its argument <i>t</i> via <i>pthread_start()</i>.
Therefore, even though it's a static (object-less) function, it knows
what object is being threaded. So it just calls the right <i>act()</i>
method and presto. Finally, once <i>act()</i> returns, the object is
deleted by performing something like a virtual seppuku.

<pre>
void *Thread::start(Thread *t) {
    try {
	t->act();
    } catch (string s) {
	cerr << s << "\n";
    } catch (...) {
	cerr << "Thread threw an exception\n";
    }

    // Seppuku
    delete (t);
    return 0;
}
</pre>


<h2>Caveats and Improvements</h2>

<ul>

  <li>
    Exception handling in the above code is <i>string</i>-based only.
    After all, it's only a demo. If you want to incorporate this code
    into your own programs, make sure that the caught exceptions match
    whatever your program is throwing.
  </li>

  <li>
    The code is pretty much tailored to my needs in Crossroads. E.g.,
    the automatic <i>delete</i> in <i>Thread::start()</i> might not be
    what you desire... A more generic class <i>Thread</i> could make
    this optional, e.g., using some boolean flag.
  </li>

</ul>

 
</description>
   </item>
   <item>
    <title>Crossroads mailing list</title>
    <link>http://www.kubat.nl/pages/blogaria/106#106</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 
<ul>

  <li>
    
    Incase you're a Crossroads user: there's now a mailing list.
    See <a href="http://crossroads.e-tunity.com/contact.xr"
    target="_blank">http://crossroads.e-tunity.com/contact.xr</a> for
    details. <a href="mailto:karel@kubat.nl">Mail me</a> if you want to
    be on it. It's "status experimental" for now.
  </li>

  <li>
    As a by-product, I have now a really simple listserv-like thingy
    tool. See the category <a href="/pages/simplelistserv">Simple
    listserv</a> on this site.
  </li>

</ul>

 
</description>
   </item>
   <item>
    <title>Crossroads 2.00 is out</title>
    <link>http://www.kubat.nl/pages/blogaria/105#105</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <center>
  <b>Crossroads 2.00 is out!</b>
</center>

<p/>
<img src="/bld/k/happy.jpg" class="floatright"/>I quite feel like Die Hard 4.0 guys. It's Crossroads, but quite
different... it might deserve a new name, but then again, it should be
obvious that it's related to the old product.. Ummm so let's just give
it a major version upgrade. Hence, 2.00. (I just hope that Crossroads
2.00 won't be as stupid as DH4.)

<p/> It <i>is</i> like the old Crossroads 1.80 series. It's still a
software balancer and dispatcher for TCP. It still supports raw TCP,
but also has HTTP goodies. It still has the most often used
dispatching algorithms.

<p/> But it's also quite different. Crossroads 2.00 is a
multi-threaded daemon (doesn't fork, should be faster and use less
resources), it doesn't use a configuration file (but commandline
options), and it's written in C++. The main executable is now
called <i>xr</i>, to distinguish from the old one.

<p/> If you feel like it, give it a go. It can be downloaded from
<a href="http://crossroads.e-tunity.com"
target="_blank">http://crossroads.e-tunity.com</a>. It has also a
Freshmeat page at <a href="http://freshmeat.net/projects/crossr/"
target="_blank">http://freshmeat.net/projects/crossr/</a>. The new
entry was just approved..

<hr/>
<p/> Good buddy Eddie remarked: <i>"So that's why you weren't in
  Azeroth...."</i>
<center>
  <img src="http://www.kubat.nl/bld//CrossroadsFreshmeatAnnouncement.png"/>
</center>
 
</description>
   </item>
   <item>
    <title>Fail Pics</title>
    <link>http://www.kubat.nl/pages/blogaria/104#104</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 If you by chance know the
site <a href="http://failblog.org/"
target="_blank">http://failblog.org/</a> then you know what "fail
pictures" are. If you don't know the site, go visit it. Anyway, whilst
on holidays, I shot two such pics myself.
<hr/>
<center>
  <h2>Faith Fail</h2>
  <img src="/bld/FaithFail.jpg"/></center>

<hr/>

<center>
  <h2>Do you do inlaws too?</h2>
  <img src="/bld/FamilyButcher.jpg"/></center>
 
</description>
   </item>
   <item>
    <title>The Fish Dance</title>
    <link>http://www.kubat.nl/pages/blogaria/103#103</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The WoW avatar of my Good buddy Eddie has found a fish to hold. Good
fun. Reminds me of... <p/>

<img src="http://www.kubat.nl/bld/Creamfudge-Fish.png">

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/IhJQp-q1Y1s&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/IhJQp-q1Y1s&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object>

 
</description>
   </item>
   <item>
    <title>Big Bother and Massive Data Storage</title>
    <link>http://www.kubat.nl/pages/blogaria/102#102</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="http://www.kubat.nl/bld/Sophie-in-t-Veld.png" class="floatleft"/>

Despite protests, despite reasoning, we can't seem to turn the tide:
massive storage of of our data is on the rise. Most recently it
appears that the European Union (EU) are engaged in talks with the USA
to exchange information regarding its citizens: credit card data,
internet browsing trails, and so on. How come so little people know or
care about this?

<p/> Fortunately, some people seem to care, and provide enough
background information. For Dutch speakers: read
<a href="http://eddie.niese.net/20080629/big-brother-weer-een-stapje-dichterbij/"
target="_blank">Ed's blog</a>. 

<p/> Who are those decision-makers and politicians that don't seem to
care about our privacy? Who are those people who are using 
mass-hysteria and the "omni-present threat of terrorism" to push on,
regardless of the effectivity of what they're doing, and regardless of
harmful side effects? Is there no-one to counter such ideas?

<p/> There's one voice, <a href="http://www.sophieintveld.nl"
target="_blank">Sophie in 't Veld</a>, who holds a seat in the
European Parliament for the Netherlands. She writes about privacy and
especially the disregard for this by most decision-makers. She also
writes about the lack of results of large-scale data acquisition and
-analysis in her blog entry
<a href="http://www.sophieintveld.nl/news/item/De_Mythe_ontzenuwd__Massale_gegevensopslag_kan_terrorisme_niet_voorkomen/"
target="_blank">The Myth busted: Massive data storage cannot
prevent terrorism.</a> According to Ruud Oord (security advisor of
the financial sector and of our Dutch national airport Schiphol),
large-scale data storage and profiling doesn't help to find the
proveribial terrorist needle in the haystack of airline passenger
movements. The British representatives in the EU confirm this.

<p/> Sophie in 't Veld is member of D66, a small Democratic  She's
getting my voice, that's for sure. 
 
</description>
   </item>
   <item>
    <title>MMV One of omitted Unix tools</title>
    <link>http://www.kubat.nl/pages/blogaria/101#101</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="http://www.kubat.nl/bld/k/happy.jpg" class="floatright"/>
Today I had to rename a bunch of files to a new name. Well almost a
new name, except for a different number in them. The files were
something like <i>out01</i>, <i>out02</i> and so on, and the new names had to
become <i>Job-Output-01.txt</i>, <i>Job-Output-02.txt</i> etcetera.

<p/>
Not too bad if you have only 2 files to rename. But what if you have
between 70 and 80? You might consider a <i>for</i> loop in a shell
script, or write up a Perl oneliner. You might however also consider
getting <b>mmv</b>.

<b>Mmv</b> is quite old, it was written in 1990 by Vladimir Lanin.
In my opinion it's one of the oh-so-handy tools that should've made it
into the GNU Fileutils package, but didn't. Because, with <b>mmv</b>,
you can simply type:

<p/>
<center>
  <b>mmv 'out*' Job-Output-=1.txt</b>
</center>

<p/>
The magic marker <i>=1</i> denotes that this part in the target name
will be taken from the first wildcard expansion in the source name;
i.e, whatever follows <i>out</i>. Note also that the source argument
is enclosed in quotes to prevent shell commandline expansion.
Incidentally, the same handy tool is also a
multiple-copy-tool <i>mcp</i>, a multiple-append-tool <i>mad</i> and a
multiple-linking-tool <i>mln</i>.

<p/>
Where can I find such a handy thingy, you might ask? Seek no further:
download <b>mmv</b> <a href="http://www.kubat.nl/mmv.tar.gz">right
here</a>. Once you get the distribution, proceed as follows:

<ul>

  <li> Unpack the archive in a suitable 'sources' directory, e.g.
  <i>/usr/local/src/</i>. The archive spills into a subdirectory
  <i>mmv/</i>.</li>

  <li> Change-dir into <i>mmv/</i> and type <b>make install</b>. This
  installs it all under <i>/usr/local/bin</i>
  and <i>/usr/local/man</i>. If you don't like these directories, edit
  the <i>Makefile</i> and define your own favorite installation
  destination.</li>

  <li> Done! Bask in the glory. The power of your fingers has just
  been expanded with <i>mmv</i>, <i>mcp</i>, <i>mad</i>
  and <i>mln</i>. And of course with <i>man mmv</i>.

</ul>

I made some minor modifications to the <b>mmv</b> source set; all are
marked with <i>KK</i>. So do a <i>grep KK *</i> if you want to see
what I changed. Basically I only made sure that the sources compile on
newer Unices. The original distribution is still under <i>dist/</i>.

<p/> Have fun with <b>mmv</b>!

 
</description>
   </item>
   <item>
    <title>Even anonymous breadcrumbs can give you away</title>
    <link>http://www.kubat.nl/pages/blogaria/100#100</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="http://www.kubat.nl/bld/MobilePhones.jpg" class="floatleft"/>
I wrote <a href="http://www.kubat.nl/pages/blogaria/53#53">earlier</a>
about the fact that we all leave 'electronic breadcrumbs' behind us as
we navigate the real and the virtual world. It now appears that the
data trail at your telecom provider can give you away even when
personal data are anonymized.
From <a href="http://mobile.slashdot.org/mobile/08/06/08/0635202.shtml"
	target="_blank">Slashdot</a>:

<p/>
<i>"'New research that makes creative use of sensitive
  location-tracking data from 100,000 cellphones in Europe suggests
  that most people can be found in one of just a few locations at any
  time, and that they do not generally go far from home.' More
  interesting than their conclusion, however, is how they got their
  data. 'The researchers said they used the potentially controversial
  data only after any information that could identify individuals had
  been scrambled. Even so, they wrote, people's wanderings are so
  subject to routine that by using the patterns of movement that
  emerged from the research, "we can obtain the likelihood of finding
  a user in any location." The researchers were able to obtain the
  data from a European provider of cellphone service that was
  obligated to collect the information. By agreement with the company,
  the researchers did not disclose the country where the provider
  operates.' Any guesses which European country requires cell phone
  providers to record where their customers make calls, and then
  allows them to give that data away without disclosing that they have
  done so?"</i>

<p/> More on this is
on <a href="http://www.nytimes.com/2008/06/05/science/05mobile.html?ei=5070&en=24843d9abeab5088&ex=1213416000&emc=eta1&pagewanted=print"
      target="_blank">the
  New York Times site</a>.

<p/> Is this shocking? Hardly. But it is another reason why large
datacollections of personal data are plain bad. Even when they're
anonymized. 
 
</description>
   </item>
   <item>
    <title>Crossroads in Argentina</title>
    <link>http://www.kubat.nl/pages/blogaria/99#99</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 On May 21st I received a very nice mail from Andrew P., admin and developer at
of <a href="http://www.alkon.com.ar"
target="_blank">www.alkon.com.ar</a>:

<p/>
<i>"Hi, my name is Andres and i'm the sysadmin and main web developer
  of www.alkon.com.ar, a south american website that has >250.000
  users and gets 2.000.000 pageviews every month. 
  We are very proud of telling you that we have been using crossroads
  for 6 months now with excellent results.  
  You are making a hell of a job, please, keep doing it."</i>

<p/> It's truly very rewarding when my pet
<a href="http://crossroads.e-tunity.com"
target="_blank">crossroads</a> is used in the real world, and even
receives good reviews. I had a great mood that day!
 
</description>
   </item>
   <item>
    <title>The Party at the Company Outing</title>
    <link>http://www.kubat.nl/pages/blogaria/98#98</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Some parodies are really funny. This one is totally hilarious. For
Dutch speakers. 

<p/>
<center>
  <object width="425" height="355"><param name="movie"
  value="http://www.youtube.com/v/C2edl0oHoVk&hl=en"></param><param name="wmode"
  value="transparent"></param><embed src="http://www.youtube.com/v/C2edl0oHoVk&hl=en"
  type="application/x-shockwave-flash" wmode="transparent" width="425"
  height="355"></embed></object>
</center>
 
</description>
   </item>
   <item>
    <title>Crossroads 1.80 is out</title>
    <link>http://www.kubat.nl/pages/blogaria/97#97</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="/bld/Crossroads-quilt.png" class="floatleft"/>
  Crossroads, my pet load balancer and failover utility for all kinds
  of networked systems, has received a new version: 1.80.
  This version produces slightly less error
  logging and fixes some bugs. Most importantly, in HTTP mode, "300"
  responses are correctly handled. Previously such responses (such as
  "304 not modified") would hamper deep header inspection mode.
  (Thanks, Oleg D. for the analysis of this problem!)
  Details are available <a href="mailto:karel@kubat.nl">upon
  request</a>.

  <p/> Anyway, if you feel like it, give 1.80 a try. Crossroads can be
  downloaded at <a href="http://crossroads.e-tunity.com"
  target="_blank">http://crossroads.e-tunity.com</a>. 

 
</description>
   </item>
   <item>
    <title>Where does technical innovation really come from</title>
    <link>http://www.kubat.nl/pages/blogaria/96#96</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The technology around us is changing and evolving, and it's doing so
in a more and more rapid way. I know, your grandma doesn't really
grasp the concept of the Internet (if there is such thing as a
'concept' of this) - but do you know what Cross Site Request Forgery
(CSRF) means? Or for that matter, what will the impact be of Google's
mobile phone software?

<p/> The innovation appears to accelerate as I watch it. But, where
does all this innovation come from? Recently I overheard a report on
the R&amp;D investments of large companies; ordered by their
investments in R&amp;D. Is that where innovation is driven?

<p/> There are big names in the list. Top dog is (of course)
Microsoft, with a 3+b$/y investment in R&amp;D per annum. Yes, that's
b for billion, 10e9. Other big names are Oracle, HP, Cisco, IBM,
Yahoo! (not in any particular order). What struck me as odd, is that
Apple is at a meagre tenth spot. How odd, those guys have produced the
arguably best-ever music player, the best-ever photo/video/music
software, and a very cool looking and perfectly working Unix system,
aimed at the large crowds. They've augmented this with cool-looking
and perfectly working WiFi systems, backup systems, etc. With only
less than a tenth of Microsoft's R&amp;D's investment! So what is
going on here?

<p/> Tonight I downloaded the
<a href="http://www.mozilla.com/en-US/firefox/all-beta.html"
target="_blank">Firefox 3 beta</a> for MacOSX. I hadn't gotten around to
downloading it before, and I had been quite happy with 2.x. Well, version
3 rocks. It looks great, renders great, loads faster than 2.x, it's
available for all platforms. Now that's a fine bit of innnovation,
right there. So where does this innovation come from? It isn't in the
top 10 budget of R&amp;D investments of the above-stated companies,
that's for sure.

<p/> This type of innovation is in my opinion the real thing - this is
what keeps Microsoft, IBM, HP, and all others on their toes. Besides
Firefox there's of course Linux, FreeBSD, GNU, OpenOffice, OLPC and
what not. Without such projects, I'm sure that Intel and Microsoft
would never have jumped on the wagon of low-cost computing platforms
for third world countries. Similarly, as I'm no stranger to
self-flattery, I think that without
<a href="http://crossroads.e-tunity.com"
target="_blank">Crossroads</a> and other load balancers, Cisco would
have never lowered the price of their stuff.

<p/> But it's not about forcing the lowering of prices. It's not about
denying companies their profits. What is is about, is providing good
qualiy and low-cost software to everyone. The era of exclusive
software, where a good text processor was like caviar, is over.
Software is nowadays simply the food, water, and electricity of
every-day life - a commodity product. Everyone uses it, everyone
relies on it, and everyone should be assured that it's good and
wholesome, just like you can rest assured that your tap water is fit
for consumption.
<a href="http://www.freesoftwaremagazine.com/columns/2008_google_summer_code_21_projects_im_excited_about"'
target="_blank">Free software Magazine</a> has even made educated
guesses as to what software will be become more of a commodiy next
year - the predictions range from more document integration to gaming,
office applications and multimedia.

<p/> The days of exclusivity of software are gone, and
for that matter, huge license fees are a thing of the past. We're all
willing to pay a few bucks for Apple's iWork, 'cuz it gets us a nice
DVD and a booklet. But who in their right mind will pay 800+ euro's
for a DVD with Microsoft Office Pro, with
<a href="http://www.openoffice.org" target="_blank">OpenOffice</a>
'round the corner?

<p/> Some big companies think that other companies are their main
competitors. Other, smarter, big companies think that open source
software is their competitor. I think that the market has simply
changed - there is no competitor to blame. Good software is a
commodity. We're so dependent on it, that it should in fact be added
to the Bill of Rights: "Everyone should be entitled to good, working
software." Just as everyone should receive to health care, should be
able to get a job, should be free of discrimination, and so on.

<p/> So I, as a consumer. Should I support certain companies, should I
get products from HP, Cicso or Microsoft? In my opinion, no, unless
they produce something that I really want. They do not drive
innvation, their goal is to keep software exclusive - as opposed to
commodity. They don't deserve my support unless they "do good". 

<p/> 'Nuff ranting. Off to bed now.
 
</description>
   </item>
   <item>
    <title>Corporate bs generator</title>
    <link>http://www.kubat.nl/pages/blogaria/95#95</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Yesterday, EvR / <a href="http://beerholder.blogspot.com/"
target="_blank">[BOFH]Basilisk</a> showed me a neat file with totally
meaningless phrases which are perfectly usable to generate those
annoying company-wide e-mails to inform all employees of the
newest-and-bestest things that management came up with.

<p/> Unfortunately, there was only the file with the phrases - and not
the generator itself. That's not right! But fortunately it can
be <a href="http://www.kubat.nl/pages/bsgen">easily corrected</a>.

<p/> But how good are computers at generating BS? Will they ever be as
good as humans?
The <a href="http://www.kubat.nl/pages/bsgen">generator</a> is a neat
start, but it has a long way to go before it can match
<a href="http://www.techcrunch.com/2007/02/14/text-of-email-to-all-yahoos/"
target="_blank">Yahoo's mail to all employees</a>. Ah there's a fine
read.. 
 
</description>
   </item>
   <item>
    <title>Even the Vatican has to adapt</title>
    <link>http://www.kubat.nl/pages/blogaria/94#94</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="http://www.kubat.nl/bld/Michelangelo-Creazione-Di-Adamo.jpg"
     class="floatright"/>
Even the Vatican has to adapt - eventually. The
<a href="http://news.bbc.co.uk/2/hi/europe/7399661.stm"
target="_blank">BBC</a> reports that the Vatican, or more precisely
the Vatican Observatory, states that extraterrestrial life may exist,
and that it might've been created by God. According to the director of
the observatory:

<p/> <i>"Just as there are multiple forms of life on earth, so there
could exist intelligent beings in outer space created by God. And some
aliens could even be free from original sin."</i>

<p/> Wow! Free from sin! That must be cool.. 'cuz we are all hampered
by the Adam and Eve's original bad idea of eating apples. That's why
we've been cast out of the Garden of Eden, right? That's why we're
condemned to suffer anything from outright catastrophes (like the
earthquake in China) to daily nuisances (traffic jams)! Finally, it
all makes sense.

<p/> So how about previous blatant mistakes of the Catholic church,
like the condemnation of Galileo's heliocentral model of the
universe? <i>"Mistakes were made, but it is time to turn the page and
look towards the future."</i> Ah.

<p/> And what about the statement that the Earth is about 10.000 years
old, and that evolutionary evidence like fossiles were placed in the
Earth's crust just to annoy scientists? Another mistake?

<p/> Now many more mistakes will have to be admitted to support an
-albeit changing- Catholic thought model, while much more plausible
models for the Universe exist? Why should we blindy trust some ideas
about an All-knowing Supernatural Being, while science provides models
that are more logical, open to discussion, and -best of all- open for
experimental verification? Guess I'm just an atheist. Or just too
stupid, which would make me an agnostic.

<p/> What is it that keeps people running home to supernatural
concepts whenever they see things they don't understand?
 
</description>
   </item>
   <item>
    <title>Big Brother is watching your dog</title>
    <link>http://www.kubat.nl/pages/blogaria/93#93</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="http://www.kubat.nl/bld/CCTV-Camera.jpg" class="floatleft"/>
Given my predisposition for privacy-related issues: this is too good
to skip. A few days
ago, <a href="http://www.cnet.com/8301-13739_1-9939635-46.html"
target="_blank">CNET</a> reported on the effectiveness of
closed-circuit TV (CCTV) systems in the UK (which incidentally has the
most camera's per capita, and is in that sense the Biggest Brother,
ever since the let's-do-all-we-can-to-fight-terrorism panic of the
last years).

<p/> Guess what.

<ul>
  <li> The camera's didn't help in terrorism-related crime fighting,
  which is their prime purpose.</li>

  <li> They helped on only 3% of the 'normal' crime cases. A very
  meagre result. </li>

  <li> They did help in a number of other obviously very important
  situations. Here's a few examples of their usage:

    <ul>
      <li> Investigation of littering; </li>
      <li> Checking the misuse of disabled-persons parking
      passes; </li>
      <li> Verifying damage claims; </li>
      <li> Spying on a person who'd called in sick; </li>
      <li> And the best ever: park surveillance to check on dog
      fouling.</li>
    </ul>
  </li>
</ul>

<p/>
<img src="http://www.kubat.nl/bld/Dogshit.jpg" class="floatleft"/>
So basically, a multi-billion installation of CCTV circuits, with
trained and qualified personnel watching the images, changing tapes,
archiving data carriers for long periods and what not, is used to check
whether British dogs shit in parks. Bloody brilliant.

<p/> From the article: <i>"Is this surprising? Not really. Just as
we've seen in the U.S., once law enforcement and intelligence agencies
are given new unchecked powers, abuse tends to happen. The more
secretive and unchecked the powers, the more widespread the
abuse." </i> In this case we're simply lucky that the 'abuse of
unchecked powers' is directed at dog shit. So far. 
	  
<p/>
 
</description>
   </item>
   <item>
    <title>666 all over the place</title>
    <link>http://www.kubat.nl/pages/blogaria/92#92</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img src="http://www.kubat.nl/bld/k/scared.jpg" class="floatright"/>

Ooh my! The Devil's Number is creeping up on us! Read
on <a href="http://news.slashdot.org/article.pl?sid=08/05/09/1721239"
      target="_blank">Slashdot</a>:

<p/>
<i> "The estimated population of the world will pass 6,666,666,666
  today. No doubt an interesting number for people everywhere (not
  referring to any religion connotations). [...] An interesting
  coincidence, the estimated number of available IPv4 addresses is
  getting very close to 666,666,666. It should cross over today as
  well."</i>

<p/>
And what's more... if you live in the Netherlands, there is probably a
number 6 in your telephone number! (Dutch phone numbers have 9
significant digits, and <i> 1 - 0.9<sup>9</sup></i> is 0.61258, so that's
a 61% chance...) <br/>
<b>Update:</b> There's even a 6 in that 61% chance! Aargh!
 
</description>
   </item>
   <item>
    <title>Security and privacy are incompatible</title>
    <link>http://www.kubat.nl/pages/blogaria/91#91</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 "If you want more security, you'll end up with less privacy." Sure
thing, Tony. Unfortunately many institutions would have us believe
this. Maybe they actually think it's true, maybe it's because once we
stop disagreeing, lots of privacy-decreasing measures can be
effectuated, without all the nagging. "If you're pro-privacy, you must
be anti-security!" Yeah, right.

<p/> From the recent news: US government agencies will start
collecting DNA of everyone who's gets arrested, whether brought to
trial or not, whether found guilty or not -- so reports
<a href="http://news.yahoo.com/s/ap/20080416/ap_on_go_ca_st_pe/dna_collection"
target="_blank">Yahoo</a>. Apparently the permission to do so was
passed long ago in the 911 aftermath, when just about anything was
allowed, as long as it would be good for security.

<p/> So why does a good doorlock increase security, while it's not
privacy-related at all? Why do good seat belts and airbags increase my
security while driving, while they are in no way related to my persona
when they are fit into the car? I'll even bet that seat belts and
airbags have saved more lives than all anti-terrorist measures put
together.

<p/> It's a sad thing that Joe Average isn't impressed by the lives
that are saved by seat belts, but instead is frightened by drive-by
shootings and terrorist attacks. If he'd look at things from a
rational perspective, he'd see that money spent on DNA databases and
no-fly lists is basically wasted. Has anyone wondered how many lives
insulin has saved, and how much each saved life has cost, as opposed
to the moneypit of so-called security measures that don't help at all?

<p/> And I've not even begun fulminating about the privacy impact
of DNA gathering,
of <a href="http://www.kubat.nl/pages/blogaria/51#51">retaining flight
data</a>,
<a href="http://www.kubat.nl/pages/blogaria/72#72">mindless logging of
website visits</a>, the
grave <a href="http://www.kubat.nl/pages/blogaria/63#63">effects</a>
of <a href="http://www.kubat.nl/pages/blogaria/88#88">identity
theft</a> and/or mistaken identities. Who's to guarantee that the
DNA database won't be leaky, that it will be handled by
trustworthy, reliable and responsible personnel, that it's security
technology will state-of-the-art, so that
<a href="http://www.kubat.nl/pages/blogaria/56#56">data
exposure</a> will never occur?

<p/> I bet that the same agencies who have initiated the DNA store
will vouch for its security. Here's another recent news bit. The
Oklahoma Dept. of Corrections had a data store of sexual offenders,
with a nice web frontend.
<a href="http://thedailywtf.com/Articles/Oklahoma-Leaks-Tens-of-Thousands-of-Social-Security-Numbers,-Other-Sensitive-Data.aspx"
target="_blank">The Daily WTF</a> has a great article on this. The
site had plain SQL in the URL's of the pages.. as in:

<pre>
http://docapp8.doc.state.ok.us/pls/portal30/url/page/sor_roster?
 sqlString=
  select distinct o.offender_id,doc_number,o.social_security_number,
                  o.date_of_birth,o.first_name,o.middle_name,o.last_name,
                  o.sir_name,sor_data.getCD(race) race,
                  sor_data.getCD(sex) sex,l.address1 address,l.city,
                  l.state stateid,l.zip,l.county,
                  sor_data.getCD(l.state) state,l.country countryid,
		  sor_data.getCD(l.country) country,
		  decode(habitual,'Y','habitual','') habitual,
		  decode(aggravated,'Y','aggravated','') aggravated,
		  l.status,x.status,x.registration_date,
		  x.end_registration_date,l.jurisdiction
  from registration_offender_xref x, sor_last_locn_v lastLocn,
       sor_offender o, sor_location l ,
       (select distinct offender_id
        from sor_location
	where status = 'Verified' and upper(zip) = '73064' ) h
       where lastLocn.offender_id(%2B) = o.offender_id
         and l.location_id(%2B) = lastLocn.location_id
	 and x.offender_id = o.offender_id
	 and x.status not in ('Merged')
	 and x.REG_TYPE_ID = 1
	 and nvl(x.admin_validated,to_date(1,'J')) >=
	     nvl(x.entry_date,to_date(1,'J'))
	 and x.status = 'Active' and x.status <> 'Deleted'
	 and h.offender_id = o.offender_id
  order by o.last_name,o.first_name,o.middle_name
 &sr=yes
</pre>

(BTW I formatted this crazy URL. Just had to see what's inside for
myself.) Now this is a true WTF. What were those developers doing when
they wrote this? What were they thinking?

<p/> So the Oklahoma Dept. of Corrections brought a website live with
a totally open portal into its database, filled with privacy-sensitive
data. And at the same time, largescale DNA gathering is supposed to be
a good idea, and no, it's not a waste of money, and yes, the security
around it will be state-of-the-art. Sure thing, Tony.

<p/> Unfortunately I'm not just flaming USA-related stuff. If only
things were that simple. These stupidies arise all 'round us, no
matter on which continent you are. There's no escaping.

 
</description>
   </item>
   <item>
    <title>The Hallmark E Card</title>
    <link>http://www.kubat.nl/pages/blogaria/90#90</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Suddenly there's a great Hallmark E-card in my inbox. Ah, how nice. Someone's
thinking of me.

<p/>
<img src="http://www.kubat.nl/bld/HallmarkCard.png" class="floatright"
       alt="Hallmark E-Card"/>

<p/> Hmmm.. I wonder who that is. Being the cautions netizen that I am, I
of course check whether it's the real thing. Let's see what the "send
one" link is about.

<p/>
<img class="floatright"
     src="http://www.kubat.nl/bld/HallmarkCardSendOne.png"/>
The link leads to hallmark.com. Hmmm. Looks authentic 'nuff.

<p/> Ok, let's check the "view" link then. <img class="floatright"
	 src="http://www.kubat.nl/bld/HallmarkCardView.png"/>
Whoops! The site h1.ripway.com doesn't sound like hallmark! Oh my, is
someone trying to trick me into clicking on a link and
infecting myself?

<p/> And then of course curiosity gets the better of me. I wonder what
that URL http://h1.ripway.com/telnet/tender.scr is about? So let's
try <code>wget -SO- http://h1.ripway.com/telnet/tender.scr |
more</code>....

<p/>
<img src="http://www.kubat.nl/bld/HallmarkCardWget.png" class="floatright"/>

<p/> ROFLMAO, the sods who are spamming this crap have run out of
bandwidth. That's not the way to Global Domination you l33t l0z3rz.

<p/>

 
</description>
   </item>
   <item>
    <title>Crosroads Solaris port is out</title>
    <link>http://www.kubat.nl/pages/blogaria/89#89</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The latest version of my pet
project <a href="http://crossroads.e-tunity.com"
	   target="_blank">Crossroads</a>, version 1.79, is finally
out. Oh how I struggled to get a good Solaris 10 port out! (Thanks go
to Oleg D., for his feedback and tireless testing!)

<p/> Anyway it's finally there. The subtle differences between Linux and
FreeBSD (MacOSX) on one hand, and Solaris on the other hand, have
again surprised me. There are some basic implementation differences,
e.g., on Solaris you can't <code>getrlimit(RLIMIT_MEMLOCK)</code>, it
just isn't there.

<p/> Plus, the handling of NULL pointers under Solaris is way
stricter. Lenient systems will allow you to <code>syslog(loglevel, "%s",
  nullpointer)</code> (where of course nullpointer is a null pointer
;-). The logged message will simply state "NULL". Not Solaris. It
isn't lenient at all. It crashes with a segmentation fault. Ah well,
that will teach me to avoid sloppy programming.
 
</description>
   </item>
   <item>
    <title>Identity theft can cost you dearly</title>
    <link>http://www.kubat.nl/pages/blogaria/88#88</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img class="floatleft" src="http://www.kubat.nl/bld/SimonBunce.jpg"
     alt="Simon Bunce"/>
Today the BBC
<a href="http://news.bbc.co.uk/1/hi/magazine/7326736.stm"
   target="_blank">reported</a> how identity theft can cost you more
than just cash. Simon Bunce used to shop on the Internet using his
credit card, and fell victim to identity theft. He only found out
after his credit card details showed in payments related to child
pornography.

<p/> Simon's nightmare was about to start. He was arrested by the
British police, lost his job, was cut off by his relatives, and almost
had to sell his family home. The police was taking months to
investigate, so finally Simon took matters into his own hands. He
obtained the records related to his case, and found out that the IP
address where his credit card details were misused, was located in
Indonesia. The child pornography related purchases were made at the
same time he was in a London restaurant, using his physical credit
card.

<p/> So finally he was able to convince the police that he had fallen
victim to a case of identity fraud. Too late. He managed to find
another job, but earns only 25% of his former salary.

<p/> The moral of the story?

<br/>
<center>
  <b>Credit card details != A living person</b>
</center>
<br/>

Everyone assumes that if your credit card number shows up, then you
must've purchased something. Not necessarily true. The police, Simon's
employer and his relatives had found him guilty based on this
assumption, which turned out to be a false one. My prediction is that
we'll see an increase in the percentage of mismatches between an
electronic data trail and a physical identity. Identity theft is on the
rise, and therefore, the reliability of electronic data is going to
decline.

<p/> People don't like uncertainty, that's the problem right there.
It's much more convenient to assume that a log record of an
electronic transaction is simply "the truth", while in fact it's only
an observation, with a chance of being false positive, and with a
chance of being false negative. We should start thinking of electronic
data in the same manner we think of medical symptoms: fever may mean
that you've caught a flu, but doesn't have to. And you may have a
flu without running a fever.

<p/> In the case of the reliability of electronic data trails, the
path gets even more slippery. The chance of hitting a false positive
is not a fixed one: it will increase as identity theft occurs on a
larger scale, it may decrease as we find measures aginst such thefts,
and I'm sure it's dependent on a variety of other factors.

<p/> In Simon's case, it's pretty obvious that neither the police, nor
his employer, nor his relatives thought this way - even despite the
graveness of the accusation. In my opinion at least the involved
police officers should've used their brains; they are supposed to be
the professionals here. The idiotically simple proof of innocence that
Simon Bunce finally delivered himself, should have been delivered by
the police, long before making accusations.
 
</description>
   </item>
   <item>
    <title>Crossroads can already do that</title>
    <link>http://www.kubat.nl/pages/blogaria/87#87</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I received a very nice mail from Hamza S., about Crossroads:

<pre>
Good to see that the Crossroads website is back online. Thanks for
sending the documentation earlier; it helped a lot. We are now using
it in a test environment and should be going to production soon.

During our tests, we came across one feature which would make
Crossroads a very formidable option for load balancing solutions.
(Please remember that this option may already be in there but we
missed it.) What do you think about adding IP awareness? For example,
in our case we have two different websites running on two servers each
and we are load balancing between those two servers. On each web
server we run two sites on two different ports. If Crossroads could
listen for the same port on two or more IP addresses, it would allow
users such as us to run two or more sites on the same server on the
same port but different IP addresses. Then Crossroads would listen to
port 80 on one IP and forward it to another, while also listening on
port 80 on another IP and forwarding it to yet another IP.
</pre>

Hmmm.. I had to think about it. I did implement a statement to bind to
a specific address before, didn't I? It was actually for security
reasons: one could bind the Crossroads daemon to e.g. 127.0.0.1, so
that external calls would not be serviced. I was wondering: would this
work for Hamza's purpose?

<p/> I ran a small test on my server which has one network address
card, configured at 10.1.1.1, and a virtual IP address at 10.1.1.2.
Here's the Crossroads configuration:

<pre>
#define DEBUG yes

service google {
   verbosity DEBUG;
   port 30000;
   bindto 10.1.1.1;
   backend g {
       verbosity DEBUG;
       server www.google.com:80;
   }
}

service etunity {
   verbosity DEBUG;
   port 30000;
   bindto 10.1.1.2;
   backend e {
       verbosity DEBUG;
       server www.e-tunity.com:80;
   }
}
</pre>

And guess what.. it just worked! The URL http://10.1.1.1:30000/
yielded the Google site, and http://10.1.1.2:30000/ the e-tunity site.
Wow. This is the first time that someone asks about a new feature in
Crossroads, and it's already in there. Thinking about it, I must even
admit that this is the first time that someone asks about a new
feature in any of my programs, and it's already in there. Celebration!
 
</description>
   </item>
   <item>
    <title>A dagerous safari</title>
    <link>http://www.kubat.nl/pages/blogaria/86#86</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Disturbing news for us Mac users.

<ul>

 <li> At the latest CanSacWest conference in Canada, a
 <a href="http://www.computerworld.com/action/article.do?command=viewArticleBasic&taxonomyName=security&articleId=9072959&taxonomyId=17&intsrc=kc_top"
 target="_blank">MacBook Air was the first system to be hacked</a>.
 (The proud winner of the contest, Charlie Miller, got to keep the
 MacBook plus a cheque for 10k$). The MacBook fell pray to its
 attackers after they were allowed to work on the system itself;
 previous network-only attacks had failed. The exploit used a
 vulnerability in Safari 3.1.</li>

 <li> Safari, Mac's standard browser, has been identified having
 several security holes. Most were related to the rendering engine -
 an open source component, of which a too old version was used in
 Safari. Due to this, Windows ports of Safari were known to be
 unstable and defective. </li>

</ul>

So now it would appear that MacOSX versions of Safari are leaky too.
What a bummer. Fortunately my favorite browser is still
<a href="http://www.mozilla.com/en-US/firefox/all.html"
target="_blank">Firefox</a>, which runs great. But just out of
curiosity.. what was the nature of the hack? I'm assuming that the
embedded library in Safari was tricked into a buffer overrun
situation, with a stack smash that started <i>/bin/sh</i> as a root
process? Love to know...

<p/> Moral of the story is I guess, that it's great to use open source
components - but just as with closed-source, you just can't disregard
new versions when they come out.

 
</description>
   </item>
   <item>
    <title>Why some Java J2EE projects are inefficient</title>
    <link>http://www.kubat.nl/pages/blogaria/85#85</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This morning I received an unexpected mail message from Iwan E., one
of the architects I'm working with. We sometimes exchange ideas about
how things are, and how they should be, regarding the software
development processes at our customer.

<pre>Why some of the Java EE / J2EE projects are inefficient
... or at least suboptimal

   1. Architects are more skilled in PowerPoint, than popular Java
   IDEs (OpenOffice ist still rare in real world :-))
  
   2. It takes several DVDs, sometimes hours, even to install the
   basic infrastructure (like appserver and database)
  
   3. Some popular servers take several minutes to start and deploy -
   you have to repeat this procedure several times a day
  
   4. It takes longer to open a case (and reproduce a problem) for a
   bug of the appserver, than fix it by yourself (of course if you had
   the source :-))
  
   5. It is hard to find developer hardware, where the "enterprise"
   development tools run efficienlty - ...and because they were
   expensive, it is hard to get rid of them...
  
   6. The architects love layers and tiers - several mapping
   procedures are needed just to pass a persistent entity from the
   persistent layer to the presentation
  
   7. Everything is configurable, replaceable and mockable. The XML
   overhead is huge. The question is: When did you really needed to
   replace something in your passed projects?
  
   8. Either it is waterfallish, or agile with all buzzwords and
   strange rituals. Both sides could be extremely inefficent. It seems
   like sometimes it is hard to be just rationale...
  
   9. Developers are sometimes too extreme: either everything is
   overengineered with millions of patterns or best practices, or
   hacked down in "go to spaghetti" fashion
  
  10. "The thrill is gone..." many developers, architects and managers
  just lost they enthusiasm and passion. This is one of the main
  reasons, why many projects are just so inefficient...
  
  11. HA, Clustering, etc. is used even for "guestbook-like"
  applications. Complexity rules!
  
  12. Strange QA rules (like documenting obvious getters/setters)
  drive the development and maintenance costs
  
</pre>

<p/>

I should like to add #13, which is totally politically incorrect:

<p/> 13. We are stuck with herds of junior developers instead of a
handful experienced developers and engineers. The corporate rationale
is that juniors are cheaper, and everything is manageable anyway. The
fact is ignored that small self-managing teams of cracks are better,
more efficient and faster. In fact fewer better developers would lead
to on-time, better and cheaper applications. 
 
</description>
   </item>
   <item>
    <title>The Hummingbird</title>
    <link>http://www.kubat.nl/pages/blogaria/84#84</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 About half a year ago I spoke with my collegue Michel Geerink about
digital photography. Whilst swapping war stories, he told me that he
had a great shot of a hummingbird in midflight. It was with his Canon
EOS350D, exposure 1/400sec, and a 400mm lens at F7.1.

<p/> Yesterday he mailed me the photo. Great work!

<p/>
<center>
  <a href="http://www.kubat.nl/bld/Hummingbird.JPG" target="_blank">
    <img src="http://www.kubat.nl/bld/Hummingbird-small.JPG"
	 border="0" width="800"/>
  </a><br/>
  <div class="small">
    Click the image for a large view. <br/>
    Copyright (c) Michel Geerink
  </div>
</center>
 
</description>
   </item>
   <item>
    <title>The Easter delusion</title>
    <link>http://www.kubat.nl/pages/blogaria/83#83</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <img class="floatleft"
     src="http://www.kubat.nl/bld/RichardDawkins.jpg"
     alt="Richard Dawkins"/>

This weekend I read an interesting interview in the NRC, a Dutch
newspaper with probably the best reputation in our small country.
They
<a href="http://www.nrc.nl/wetenschap/article984005.ece/Jezus_zou_nu_atheiuml_st_zijn"
target="_blank">interviewed Richard Dawkins</a>, a British scientist
and atheist, author of the book "The God Delusion", who is often seen
as a rabid anti-religionist. In the article Richard Dawkins retored:
"Do I look like a militant? Do I sound militant?" No, indeed he
doesn't. He rather looks like an English gentleman. But the article's
title suggests otherwise: "Jesus would now be an atheist".

<p/> Richard Dawkins appears an anti-religionist on two fronts: One,
he's a true scientist, and a Darwinist. Any theory that claims that
the Earth is less than 10.000 years old, is therefore discarded. Two,
he fights any theory that hampers education and free thinking, like
the all-too-well discussed Creationism ("Intelligent Design") that we
too often see in the USA.

<p/> Personally, I couldn't agree more. Has religion outlived its
usefulness, which it undoubtedly had centuries ago, when it helped
structure lawful communities?

<p/> Coincidentally during this Easter weekend we visited a good
friend, who lives in the countryside, and had a great time. There were
7 adults and 10 kids ranging from 6 months to 13 years, all hanging
out 'round a great pyre and enjoying good food, drink, music and
company. At one time the subject turned to the origin of the Easter
festival. Hmmmm.. let's see what we can find here.

<ul>

  <li> The Jewish religion celebrates the exodus from Egypt and
  liberation from slavery. "Pesach" probably refers to the sacrificial
  lamb. Pesach-derived terms are still widely used, such as "Pasen",
  the Dutch term. </li>

  <li> "Easter" and its German counterpart "Ostern" are probably
  derived from the goddess Eostre (Eastre, Ostara), a Germanic
  paganistic goddess of dawn. Her feast would be celebrated around the
  spring equinox and would welcome the warmer season. During the
  feast, huge bonfires would be lit to chase away the dark spirits of
  winter, to welcome the light and to welcome the fertility that the
  coming spring would bring. </li>

  <li> Also associated with fertility, are Easter eggs (and bunnies).
  What better symbol of new life could one find? In Slavonic
  countries, there are even associated traditions of men visiting
  women for the obvious purpose of courting, and being payed by
  beautifully painted Easter eggs. </li>

  <li> Finally there's of course the Christian religion, which
  celebrates Jesus' resurrection. Easter holidays end a period of 40
  days of fasting and repenting, during which probably not even eggs
  could be eaten. Maybe that's why the 'old' eggs would get painted,
  and during the feast one could safely eat the new ones?

  <li> Easter holidays are typically somewhere between the end of
  March and the end of April. How come? The 'algorithm' to compute the
  date is quite complicated:

    <ul>

      <li> Take the date of the spring equinox (March 21st in the
      Gregorian calendar), </li>
      <li> Wait until the first full moon, </li>
      <li> Wait until the first Sunday after that, </li>
      <li> And that's your Easter Sunday. </li>

    </ul>
    
  How complicated! This doesn't mix too well with Sun-based
  calendars, like the Julian or Gregorian ones. </li> 

</ul>

So there we are. When we celebrate Easter, we paint some eggs because
in ancient times they would have expired their freshness date. We eat
other eggs, because they're a symbol of fertility, light and spring.
We build bonfires, because the old Germans chased away spirits with
fire. We call it Easter holidays, because of a paganistic goddess. Or
we call it "Pasen" because of a Jewish feast. The date is never the
same because instead of being calendar-related, it depends on
the moon cycle.

<p/> And we call all this a Christian holiday. I'm pretty sure that
the early Christians modelled their feast so that it would coincide
with other paganistic feasts of that period. That's the best way to
compete with others: make sure that your feast is on the same
date, and make sure that your feast incorporates some elements of the
others (eggs, bonfires, the name) - and before you know it, you'll have more
followers than you can count.

<p/> Ah well. Personally, I don't really believe in Eostre, Eastre or
Ostara. So call me an atheist. But I do know that I don't need an
excuse to hang out with good people around a nice fire while sipping wine.
 
</description>
   </item>
   <item>
    <title>McAfee detects mass hack of 200.000 webpages</title>
    <link>http://www.kubat.nl/pages/blogaria/82#82</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
  <tr>
    <td valign="top" width="300">
      <img src="http://www.kubat.nl/bld/SecondWaveHack.png"
	   alt="Second Wave Hack article"/> <p/>
      <center>
	<div style="font-size: 8pt;">Part of the article. Edited for
	  brevity.</div>
      </center>
      <p/>
    </td>
    <td valign="top">
      Today I read at
      the <a href="http://www.itnews.com.au/News/72214,second-mass-hack-exposed.aspx"
	     target="_blank">ITNews website</a> that McAfee detected a mass
      hack of unprecedented size. Some 200.000 pages were infected! The
      first 'mass hack' only affected some 10.000 pages, so that this second
      once appears 20 times larger. It seems to affect the PHP-based
      <a href="http://www.phpbb.com/" target="_blank">phpBB</a> forum
      system.

      <p/> I was intrigued and read on. <i>"[The phpBB attack] relies
	on social engineering The infected pages bring up what appears
	to be a pornographic web site. Upon loading the page, a 'fake
	codec' social engineering attack is attempted. The user is
	told that in order to view the movie on the page, a special
	video codec must be installed. The user then downloads a
	trojan program which installs a malware package on the users
	system then delivers a fraudulent error message telling the
	user that the supposed codec could not be installed."</i>

    </td>
  </tr>
</table>

Hey, that's odd. <a href="http://www.kubat.nl/pages/blogaria/75#75">I
  wrote</a> about this type of spam more than a month ago -
  and I suggested how to fight it. The above quoted description of the
  attack is furthermore quite off, or incomplete to say the least. The
  attack vector is as follows:

<ul>

  <li> On a phpBB board, users create profiles. They can optionally enter
  their ICQ number, their hobbies, and so on - and also a 'homepage'
  URL.</li>

  <li> Distributors of malware register their name, and enter the
  homepage field, and they make sure that this field points to a site
  that is controlled by them or by their organization. </li>

  <li> Other users may see this profile, and click on the homepage
  URL. </li>

  <li> In the case of the 'second hack wave' that's described here,
  the homepage is a porn site that tries to get their visitors to
  download a 'viewer', which is in fact a trojan.</li>

</ul>

So what's the matter here? In my opinion, this 'second wave hack' is
not a true hack of webpages. Rather, it's a spam-like attempt to get
unsuspecting users to download a trojan. It's just spam, but in a
different format. All social networking sites that allow users to
self-register and to specify personal information, are potential
distribution channels. The sites themselves aren't hacked; the attack
is on a meta-level.

<p/> For example, imagine that on some social networking site, users
can see each other's email address. Then a similar attack vector is to
obtain e-mail addresses of all subscribers, to send them the trojan as
attachment, and to hope that they click on it. Here also the site is
only a distribution channel: this would not be a hack of the SMTP (e-mail)
protocol. Neither is the above described 'second wave' a hack of phpBB
based forums. A better description would be: "This attack relies on
social engineering. It uses social networking sites (in this case:
phpB forums) to entice users to download malware."

<p/> Furthermore, what bothers me, is that no information is provided
as to what the number 200.000 means. I suppose that it means that the
attackers ran scripts which in registered some 200.000 users
with a homepage link leading to a malware site. Is that a lot? As
compared to what - the total number of spam messages on websites, or
as compared to the total number of spam via e-mail? Should we fight
it? (Yes of course we should, even if we don't know the exact spread.
See my <a href="http://www.kubat.nl/pages/blogaria/75#75">previous
  article</a>.)

<p/> But how many phpBB users have actually clicked the link? How many
have actually downloaded the malware trojan? That would be ultimately
the effective number to classify this attack. Alas, I don't know.

<p/> What I do know, is that security-wise we should be painfully
aware of how attacks work, what the exact details are, and how we
should make the public aware of threats. It's no use to warn the
public against phpBB forums; unsuspecting users will avoid phpBB and
will be enticed into downloading malware via other methods.
 
</description>
   </item>
   <item>
    <title>More predictive statistics</title>
    <link>http://www.kubat.nl/pages/blogaria/81#81</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 A while ago I wrote about
some <a href="http://www.kubat.nl/pages/blogaria/80#80"> wrong statistical
conclusions</a>. Here's a nice one to add to the list.

<p/> <i>If you want to collect evidence of monsters, then
  go live on an island and name it something that starts with
  "New".</i>

<p/> The rationale is here: The only scientifically proven "monster"
is the giant squid, or Kraken. Its remains statistically wash up most
frequently on the shores of New Zealand and Newfoundland.
 
</description>
   </item>
   <item>
    <title>Backwards conclusions even on Slashdot</title>
    <link>http://www.kubat.nl/pages/blogaria/80#80</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I saw a quite unfortunate entry
on <a href="http://science.slashdot.org/article.pl?sid=08/03/10/0142258"
target="_blank">Slashdot</a>:

<p/>

<center>
 <img src="http://www.kubat.nl/bld/CatsAndHealth.png"
      alt="Cats and health on
      http://science.slashdot.org/article.pl?sid=08/03/10/0142258" />
</center>

<p/>

I see such backwards conclusions only too often. The quoted study says
that an experiment (which ran from 1976 to 1980), <b>in retrospect</b>
shows different characteristics between one group that had cats, and
another group that didn't. And then the article concludes that having
a cat influences those characteristics! What a blatant amateur error!

<p/> These errors occur frequently in newspapers and magazines, if you
look closely enough. Correlation is mistaken for cause and effect. In
some papers or magazines this will be purely for the effect of bold
headlines that sell copies. But alas, now this error has also shown up
on Slashdot. Shame on you, /.!

<p/> Incase you're interested: Statistically, you can only claim a
cause and effect relation if you randomize your testing group
regarding the presence or absence of the factor you're investigating.
In this case this would mean that in 1976, half of the sample group
would have been assigned a cat and half would have been forced to live
without one. Then, years later, the two groups would have been
compared with regard to the occurrence of heart attacks. This
obviously didn't happen in this study; therefore, there may be other
relevant factors which aren't discussed at all. For example: did the
people with cats live in the countryside, enjoying a laid back life
style, while the people without cats lived in large cities, ratracing
every day? That might be a more plausible explanation for heart
attacks than having a cat!

<p/> That's why randomising your population is so important. It
distributes all other effects (even those we can't yet think of)
evenly over the two groups. It's even better when you can do this
blindly: the sample population with the factor 'cat' wouldn't know it,
and neither would the sample population without the factor (though as
a subject in the study, it would be kind of hard <b>not</b> to know
that you have (or don't have) a cat at home). And just to state the
obvious: it's best when neither the subjects nor the investigators
know whether the factor was applied. That's a double blind experiment.

<p/> Medical literature has numerous examples of experiments where
correlation gets mistaken for cause and effect. One of the more famous
blunders was the conclusion that living in slums causes schizophrenia.
By the time the results were made public, the damage was already done.
It took years to correct this fault; closer investigation showed that
schizoid personalities are drawn to slums and will preferably live
there (as opposed to e.g. suburbia).

<p/> For all who don't like to use their brains, but instead like to
rely on mindless headlines, here are a few more 'conclusions':

<ul>

  <li> Make your kids listen to Mozart. They will have better school
  grades. (No kidding! There used to be people who made their kids
  listen to Mozart because they believed this.) </li>

  <li> Don't be poor. You will have a higher chance of being killed in
  a crime. (Ah. So if you live in a bad neighborhood and win the
  lottery, that suddenly makes your life safer? Hmmmm... On this
  individual basis, quite the opposite might be true!) </li>

  <li> Stay young, you will have better teeth. (Yeah, let's not grow
  old anymore.) </li>

  <li> Be white, instead of black. You will have an overall better
  health. (Again, large-number statistics, collected a-posteriori,
  applied predictively to individuals. In the same vein: Get straight
  short black heir, a yellowish complexion, call yourself Li, and
  you'll get better math grades.) </li>

</ul>
 
</description>
   </item>
   <item>
    <title>A fractal photograph</title>
    <link>http://www.kubat.nl/pages/blogaria/79#79</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
  <tr>
    <td valign="top" width="390">
      <img src="http://www.kubat.nl/bld/Sierpinski.jpg"
	   alt="Waclaw Sierpinski"/>
    </td>
    <td valign="top">

      Yesterday I saw a nice article on
      <a href="http://www.sciencenews.org/articles/20080216/mathtrek.asp"
      target="_blank">Sciencenews.org</a> about mathematical
      visualisations. Lots of such visualisations are of course based
      on fractals. That's why - I find - one of the nicest onces was a
      picture of Waclaw Sierpinski, one of the 'founders' of fractals
      and inventor of the Sierpinski carpet. According to the article:

      <p/>
      <i>
      "To create a Sierpinski carpet, take a square, divide it in a
      tic-tac-toe pattern, and take out the middle square. Then draw a
      tic-tac-toe pattern on each remaining square and knock out the
      middle squares of those. Continuing forever will create the
      Sierpinski carpet."</i>

      <p/> The photo is of course composed from such carpet fragments. 

    </td>
  </tr>
</table> 
 
</description>
   </item>
   <item>
    <title>Kaprekar revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/78#78</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Yesterday I wrote
about <a href="http://www.kubat.nl/pages/blogaria/77#77">Kaprekar
  numbers</a>. Just an hour later I received this mail by
<a href="http://eddie.niese.net/" target="_blank">Eddie</a>:

<p/>
<i>"Ah. I saw your blog entry about your Kaprekar numbers. With a
  proggle... I tried it out right away. Don't want to nag, but you can
  optimize that proggle somewhat."</i>

<p/> What news! Flabbergasted, I stare at the mail. First of all, Ed
uses a fantastic term for little scripts: <b>proggle</b>. That's
here to stay, Ed! Second, Ed suggests an optimization. Hmmmm... Let's
be very careful here. The famous DE Knuth already remarked that
"premature optimization is the root of all evil". Ed suggests to optimize:

<p/>
<i>"Instead of
  <pre>
    $sum   = $left-&gt;copy();
    $sum-&gt;badd ($right);
    return ($nr-&gt;bcmp($sum) == 0);  </pre>
  
  you might also:

  <pre>
    $left-&gt;badd($right);
    if ($nr-&gt;bcmp($left) == 0) {
        $sum = $left;
        $left  = Math::BigInt-&gt;new($leftstr);
        return 1;
    }
    return 0;  </pre>

  I'm removing a copy which you always perform, and I introduce a
  penalty (for the rare case that you find a Kaprekar number). The
  difference is but a few percents, but still..."</i>

<p/> 

I cannot delay! I need to test this right away. Is it a meaningful
optimization? I quickly hack together two scripts:
<a href="http://www.kubat.nl/bld/kaprekar1">kaprekar1</a> which is my
old version,
and <a href="http://www.kubat.nl/bld/kaprekar2">kaprekar2</a>, with
Ed's optimization proposal. The new scripts take a start and end value
as arguments, so that I can better compare timings.

<p/> I fire up the two versions, using <i>time</i> to check.. and...

<table>
  <tr>
    <td bgcolor="lightgray"> <b>Method</b> </td>
    <td colspan="3" bgcolor="lightgray"><b>Timings</b> </td>
    </tr>
  <tr>
    <td bgcolor="lightgray"></td>
    <td bgcolor="lightgray"><b>Real</b></td>
    <td bgcolor="lightgray"><b>User</b></td>
    <td bgcolor="lightgray"><b>Sys</b></td>
  </tr>
  <tr>
    <td bgcolor="lightgray">kaprekar1</td>
    <td bgcolor="lightgray">1m1.039s (61.039s)</td>
    <td bgcolor="lightgray">1m0.724s (60.724s)</td>
    <td bgcolor="lightgray">0m0.080s</td>
  </tr>
  <tr>
    <td bgcolor="lightgray">kaprekar2</td>
    <td bgcolor="lightgray">0m58.890s</td>
    <td bgcolor="lightgray">0m58.637s</td>
    <td bgcolor="lightgray">0m0.091</td>
  </tr>
  <tr>
    <td bgcolor="lightgray">Speedup</td>
    <td bgcolor="lightgray">3.5%</td>
    <td bgcolor="lightgray">3.4%</td>
    <td bgcolor="lightgray">n.a.</td>
  </tr>
</table>

<p/> Brilliant! Yes, the difference <b>is</b> but a few percent, but still.
That should teach me! Every often-repeated code snippet, even in Perl,
is a candidate for optimization, always.

<p/> Onward to the next proggle!

<p/>(Oh, incase you're wondering what the Kaprekar numbers are up
to 500 million: <i>9 45 55 99 703 999 4950 5050 7272 7777 9999 77778
82656 95121 99999 318682 329967 351352 356643 390313 461539 466830
499500 500500 533170 538461 609687 643357 648648 670033 681318 791505
812890 818181 851851 857143 961038 994708 999999 4444444 4927941
5072059 5555556 9372385 9999999 36363636 38883889 44363341 44525548
49995000 50005000 55474452 55636659 61116111 63636364 69115816
74747475 75247525 80226927 80726977 83409436 86358636 88888888
91838088 94520547 99999999 332999667 432432432</i>. That's it, I'm not
generating any more, have 'nuff of 'em now.)

 
</description>
   </item>
   <item>
    <title>Kaprekar numbers</title>
    <link>http://www.kubat.nl/pages/blogaria/77#77</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This morning I awoke painfully aware of yet another totally useless
bit of information in my head: Kaprekar numbers are integers, where
you can take the square of the number, chop it in two parts, add the
parts, and that sum yields again the number you started with. This
prompted me to verify this bit of information in David
Wells' <i>Penguin Dictionary of Curious and Interesting Numbers</i>,
and yes, it's how Kaprekar numbers work.

<p/> For example, 9 is a Kaprekar number: the square is 81, and 8+1 is
again 9. Also, 45 is a Kaprekar number: the square is 2025, and 20+25
is again 45. These two numbers (9 and 45) are incidentally the
smallest Kaprekar numbers.

<p/> So far so good. I got up, had my coffee, started work.. and got
dragged into a phone conference. I couldn't hang up, I couldn't
concentrate on real work.. now what. Let's doodle!

<p/> Here is the result: a little Perl script that goes from 1
upwards, and checks for Kaprekar numbers. The first version I had, was
with 'normal' Perl number handling, but that soon grinded to a halt, as
squares overflowed. So here's a version with Math::BigInt which
performs quite well, I must say. Just for fun, there's an alarm
handler which shows every 10 seconds at which number the script is.
Otherwise I might get suspicious that it doesn't work at all and stop it...

<pre>
#!/usr/bin/perl

use Math::BigInt;
use strict;

$|++;

my $nr     = Math::BigInt-&gt;new('1');
my $square = Math::BigInt-&gt;new();
my $left   = Math::BigInt-&gt;new();
my $right  = Math::BigInt-&gt;new();
my $sum    = Math::BigInt-&gt;new();

local $SIG{ALRM} = sub {
    print ("Now at ", $nr-&gt;bstr(), "\n");
    alarm (10);
};

alarm (10);
while (1) {
    print ($nr-&gt;bstr(), ' is a Kaprekar number: sq=', $square-&gt;bstr(),
	   ', left=', $left-&gt;bstr(), ', right=', $right-&gt;bstr(),
	   ', sum=', $sum-&gt;bstr(), "\n") if (kaprekar());
    $nr-&gt;badd(1);
}

sub kaprekar {
    $square = $nr-&gt;copy();
    $square-&gt;bmul ($nr);

    my $len = $square-&gt;length();
    return (undef) if ($len & 1);
    
    my $str      = $square-&gt;bstr();
    my $leftstr  = substr ($str, 0, $len / 2);
    my $rightstr = substr ($str, $len / 2);

    $left  = Math::BigInt-&gt;new($leftstr);
    $right = Math::BigInt-&gt;new($rightstr);
    $sum   = $left-&gt;copy();
    $sum-&gt;badd ($right);
    
    return ($nr-&gt;bcmp($sum) == 0);
}
</pre>

Aah, just great. Now I know that <i>9 45 55 99 703 999 4950 5050 7272
7777 9999 77778 82656 95121 99999 318682 329967 351352 356643 390313
461539 466830 499500 500500 533170 538461 609687 643357 648648 670033
681318 791505 812890 818181 851851 857143 961038 994708 999999 4444444
4927941 5072059 5555556 9372385 9999999</i> is the series of Kaprekar
numbers up to 10 million.

<p/> And above 10 million, 36363636 is another one. I think that'll be
my favorite. Always wanted to know that. Another bit of useless
information has been inserted into my brain.
 
</description>
   </item>
   <item>
    <title>A tale of the criminal ineptitude</title>
    <link>http://www.kubat.nl/pages/blogaria/76#76</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
  <tr>
    <td width="223" valign="top">
      <img src="http://www.kubat.nl/bld/AugusteRodinTheThinker.gif"
	   alt="Auguste Rodin: The Thinker"/>
    </td>

    <td valign="top">

      Today I overheard a story on the Dutch radio, which I'd like to
      share.

      <p/> A while ago, a burglary occurred in the Singer museum in
      Laren, NL. The burglars stole a few bronze statues which they
      wanted to melt for copper to make a quick buck. With today's
      high copper prize, recycling can be a very a profitable
      business. These guys had obviously a fairly loose definition of
      "recycling".

      <p/> Unfortunately for the burglars, recycling paper is not in
      their vocabulary. On the crime scene, police found a torn up
      printout of an itinerary from one of the burglars' home to the
      museum. The police proceeded by taping together the paper scraps
      and retracing the route.

      <p/> The burglars were apprehended. Today they were sentenced to
      4.5 and 4 years in prison, respectively. The statues were
      returned to the museum. One of them, Rodin's "The Thinker", was
      unfortunately damaged.

    </td>
  </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Irritating Selfregistered users in PHPBB</title>
    <link>http://www.kubat.nl/pages/blogaria/75#75</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 In my spare time, I host and administer a small <a
href="http://www.phpbb.com/" target="_blank">phpbb</a> forum. Visitors
can register their user name, a forum administrator can then activate
them, and they can participate in the forum information exchange.

<p> So far so good. But in these modern times, loads of unwanted users
self-register to advertise porn sites, which is something I don't want
to see on my forum. Besides, such "users" are no more than robots who
in their mechanical dumb fashion create the same-o same-o crap entries
over and over again. The user entries consistently show a URL in the
"user homepage" field that leads to porn sites. These sites in try to seduce
the visitor into downloading their "viewer". Yeah right. Sure, we're
all going to download that executable and run it on our system...

<p> Nevertheless, I don't want those users in my database.
Fortunately, fighting back is pretty trivial - a dumb, mechanical
silly script is enough to push back those dumb, mechanical robots.
Here's a little Perl script that does just that. If you want to use
it, then proceed as follows.

<ul>

 <li> Edit the '$db' variables at the top of the script and substitute
 your own values. </li>

 <li> Try out the script, using '/path/to/script test'. It will show
 you which users would get deleted. </li> 

 <li> If you're satisfied, try the script more, using '/path/to/script
 go'. This will actually delete the unwanted users. </li> 

 <li> If you like it, add an entry to 'crontab' to invoke the script
 regularly. I run it each 10 minutes and that works perfectly. </li>

</ul>

<pre>
#!/usr/bin/perl

use strict;

my $db = 'MyDatabaseName';
my $dbuser = 'MyDatabaseUser';
my $dbpass = 'MyDatabasePassword';
my @badwords = qw(porn penis orgy girls blonds nasty);

# Check arg list.
my $opt = $ARGV[0];
if ($opt ne 'test' and $opt ne 'go') {
    die ("Usage: $0 {test|go}\n");
}

# Create database connection.
open (my $of, "|mysql -u$dbuser -p$dbpass $db")
  or die ("Cannot start mysql: $!\n");

# Create the where clause.
my $where = 'user_active = 0 and (';
my $nbad = 0;
for my $b (@badwords) {
    $where .= ' or ' if ($nbad &gt; 0);
    $nbad++;
    $where .= "upper(user_website) like '%$b%'";
}
$where .= ')';

# List what would be deleted.
print ("Where clause:\n",
       "$where\n");
print $of ("select username, user_website from phpbb_users where $where;\n");

# Run the delete.
if ($opt eq 'go') {
    print $of ("delete from phpbb_users where $where;\n");
}

close ($of) or die ("MySQL indicates error!\n");
</pre> 
</description>
   </item>
   <item>
    <title>B2B Spam in the Netherlands</title>
    <link>http://www.kubat.nl/pages/blogaria/74#74</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td valign="top" width="570">
   <img src="http://www.kubat.nl/bld/NovistarJunkMail.png"
	alt="Junk from Novistar.nl"/>
  </td>

  <td valign="top">

   February 6th, and I'm again cleaning out some B2B spam. I've <a
   href="http://www.kubat.nl/pages/blogaria/68#68">written about this
   earlier</a>: besides consumer spam, business spam is now illegal in
   the Netherlands too.

   <p/>
   And still I'm seeing such messages. Originating from a Dutch
   address, and about the same-o stupid things that you don't need -
   in this case a CD/DVD storage box. Sheesh.

   <p/> Time to do something! So I surf to <a
   href="http://www.opta.nl" target="_blank">the Opta</a>, the Dutch
   telecom watchdog, to log a complaint.
  </td>
 </tr>

 <tr>
  <td colspan="2"> <hr/> </td>
 </tr>
 
 <tr>
  <td valign="top" width="521">
   <img src="http://www.kubat.nl/bld/OPTASpamComplaintsOnlyForConsumers.png"/>
  </td>

  <td valign="top">
  
   It takes me ages to find the right link, in this case to <a
   href="http://www.spamklacht.nl"
   target="_blank">www.spamklacht.nl</a> (literally: spam complaint),
   where I dutifully fill out a complaint form - being the
   <i>cough</i> good citizen that I am.

   <p/> Guess what. At this time, complaints can only be logged by
   consumers. Not by companies...

   <p/> Opta, please get your gear in order.

  </td>
 </tr>
</table>

 
</description>
   </item>
   <item>
    <title>Surprising iSight Capture</title>
    <link>http://www.kubat.nl/pages/blogaria/73#73</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
 
  <td width="180" valign="top">
   <img src="http://www.kubat.nl/bld/Half-asleep.jpg" alt="Karel half asleep"/>
  </td>

  <td valign="top">
   I recently wrote about <a
   href="http://www.kubat.nl/pages/blogaria/71#71">iSightCapture</a>,
   a commandline utility that I use to regularly snap the environment
   of my notebook. Funny thing is... it does just that, regularly make
   a snap. Which can lead to (not so?) surprising shots.
  </td>
 </tr>
</table>     
</description>
   </item>
   <item>
    <title>Breadcrumbs at WickedLasers.com</title>
    <link>http://www.kubat.nl/pages/blogaria/72#72</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 After an interesting article on Slashdot I recently visited <a
href="http://www.wickedlasers.com/" target="_blank">WickedLasers</a>.
Those guys sell a flashlight which is capable of setting fire to
paper! Way cool, in a nerdish sort of way. On the downside, it eats
batteries like crazy, you can operate the flashlight for about 15
minutes only, it seems.

<p/> Anyway, that's not what this entry is about. I am nerdish enough
to appreciate such a flashlight, I am however also a privacy-minded
person. While I was accessing the site, I got the following error:

<p/>
<center>
 <img src="http://www.kubat.nl/bld/01-WickedLasersSQLError.png"/>
</center>

<p/>
Apparently they were having a small database problem - can happen, no
big deal. But hey wait! Why would they be interested in inserting my
host name into their table 'hosts'? It seems that they (a) picked up
my IP address, (b) reversed it into a hostname, and then (c) tried to
store it in a database, together with the access time ("NOW()"). I
think that they're going to lengths to get this information. 
Especially the reversal of an IP address to a hostname is costly (in
terms of processing time). It's not something you do just for fun; you
only do that if you really really want the information. In my case, the
last database-related step failed, which made this action apparent. If
the database had not malfunctioned, my hostname would have been stored
without me ever noticing!

<p/> Time for Mr. Privacy Concern to step up and ask questions! And so
I did. The site lets you log tickets for the WickedLasers staff; so I
went ahead and wrote one:

<p/>
<center>
 <img
 src="http://www.kubat.nl/bld/03-WckedLasersRequestForInformationSubmitted.png"/>
</center>

<p/>
Within a day I received a friendly answer from Andrew Hammel of
WickedLasers:

<p/>
<center>
 <img src="http://www.kubat.nl/bld/05-WickedLasersAnswer.png"/>
</center>

<p/>
So yes, they do store the reversed host name. They are not trying to
mask or deny it; and apparently it's just part of some shopping cart
system they are using.

<p/> I decided that this is good enough for me at this moment. I don't
fancy riding around on a skinny horse, engaged in crusades against
windmills, and followed by a short guy on a mule. But it does
illustrate some of my ideas:

<ul>

 <li> Why does their shopping cart system need to store my hostname?
 Even more important: why did the attempt to store the hostname occur
 even before I made a purchase? </li>

 <li> Is this some odd security feature to check that, in the event
 that I should make a purchase, I am still connected from the same
 originating address? If so, I think it's a bit weird feature. </li>

 <li> How long are they storing my hostname? That question was -alas-
 not answered. </li>

 <li> Also, they failed to answer my two questions regarding the
 protection of such data, against both external and internal parties.
 </li> 

</ul>

Implementing a solid data privacy (and very much related: security) is
not something you do on a system-by-system or
application-by-application basis. It's not a "trick" that you use (or
not). Rather, it's a state of mind. And while I do believe that the
guys at WickedLasers are not malevolent, they don't appear to be in
the same state of mind as I am. What I do believe, is, that privacy
concerns will affect us all in the near future. Even the
guys at WickedLasers.
 
</description>
   </item>
   <item>
    <title>iSight Capture Utility</title>
    <link>http://www.kubat.nl/pages/blogaria/71#71</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td valign="top">

   I recently stumbled upon a commandline utility that captures a
   still image from my Mac's iSight camera. The utility is
   appropriately called "isightcapture". Great! Just what I was
   looking for! Now I can automate capturing the environment once
   every while, and forwarding the image to a secure location. If my
   Macbook ever gets stolen, who knows - I might get an image of the thief!

   <p/> (This is by no means a new idea. There's a snazzy utility
   called <a
   href="http://lifehacker.com/software/theft/hack-attack-turn-your-macbooks-isight-into-a-ftp-backed-up-security-camera-207605.php"
   target="_blank">iAlertU</a> that does the same thing. But it's commercial,
   scripted and depends on the GUI - not what I need. <a
   href="http://www.orbicule.com/products/"
   target="_blank">Orbicule</a> seems to do the same thing. But hey, I
   can do this myself and have the full freedom of scripting! And
   apparently a MacBook thief was already <a
   href="http://uneasysilence.com/archive/2006/12/8711/"
   target="_blank">caught using a similar approach</a>.)

   </p> The original server where the capture utility was hosted, is now however
   down, so I'm providing the utility from this page. If you want to
   use it:
   
   <ul>

    <li> Download the archive <a
    href="http://www.kubat.nl/bld/iSightCapture.tar.gz">iSightCapture.tar.gz</a>.
    </li>

    <li> Unpack the archive, using "tar xzf iSightCapture.tar.gz".
    </li>

    <li> Read "iSightCapture/isightcapture.rtf" for more instructions.
    </li>

    <li> Copy "iSightCapture/isightcapture" to a directory on your
    path, e.g. to "/usr/local/bin". </li>

    <li> To snap an image, enter something like: "isightcapture
    picture.jpg". </li>

    <li> If you want to snap regular images and upload them to a
    secure site, be creative! This post doesn't elaborate on that.

   </ul>

   I've written the author regarding open-sourcing this utility. Who
   knows? I hope I'll be posting the source code later on. Enjoy!

  </td>

  <td valign="top" width="180">

   <img src="http://www.kubat.nl/bld/iSightCapture.jpg"/>

   <p/>

   <div style="font-size:8pt;">This is me, testing "isightcapture". Whee, it works!
   Who's that looking over my shoulder?</div>

  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>The Male Brain</title>
    <link>http://www.kubat.nl/pages/blogaria/70#70</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
 <tr>
  <td width="151" valign="top">
   <img src="http://www.kubat.nl/bld/MannenbreinNegeertVrouw.jpg"/>
  </td>
  <td valign="top">
  
   In its Sunday edition of January 26th, the Dutch newspaper "De
   Telegraaf" (a.k.a. "De Fabeltjeskrant" - the fairytale newspaper)
   published the following story on its first page (the translation is
   fairly liberal due to my limited language skills):

   <p/> "<b>Male brain ignores women</b><br/>

   Amsterdam, Sunday. The female voice is far too difficult to
   understand for most men. This is because a man must use his whole
   brain to decode a female voice. One small brain lobe suffices to
   decode a male voice, so have discovered British scientists.

   <br/> Decoding a female voice is even so tiresome that a man would
   rather ignore it. The male brain can without difficulties shut
   itself off for high, shrieking tones. They understand only half of
   it anyway, so as far as they are concerned, they aren't missing
   much."

   <p/>
   Usually I question such odd reports of so-called scientific
   experiments and results. But in this case, I'm willing to make an
   exception and accept these results without hesitation.

  </td>
 </tr>
</table> 
</description>
   </item>
   <item>
    <title>Searching for the next Uri Geller</title>
    <link>http://www.kubat.nl/pages/blogaria/69#69</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
 <tr>
  <td valign="top">

   The Dutch commercial TV station SBS6 has reached yet a new
   milestone in its search for banality. Tonight a much advertised
   show is airing at 8pm, called "Who will be the next Uri Geller?"
   The Grandmaster himself will make his appearance in a series of
   shows where promising young psychics will be judged. "Already the
   most talked-about show of 2008!" Yeah right.

   </p> Let's not forget the true Grandmaster of the Uri Geller age:
   James Randi, founder of the Sceptic Society and famous buster of
   charlatans, pseudo-psychics and other make-believers who make their
   fortune by robbing the all-to-gullible public. For decades, Mr.
   Randi has been exposing tricksters who claim that they possess
   supernatural powers of mind. There is even the famous One Million
   Prize to be won: if you can perform some feat, which cannot
   otherwise be explained by scientific methods, then James Randi
   himself will give you one million dollars. There's a catch though -
   you have to perform your trick in a controlled environment, under
   scrupulous watchful eyes of cameras, trained personnel and
   sometimes James Randi himself. Should I add that no-one has yet won
   this prize, or is that obvious enough?

   <p/> The following video is a very nice summary of James Randi's
   work regarding Geller, including comments by James Randi. There's
   one remark that Mr. Randi makes that really strikes home: "Why
   would you believe in psychic powers, when other explanations are
   much more plausible?"

   <p/> Enjoy, stay sceptic, and use your own brain - don't rely on other
   people's mental powers.

  </td>
  <td valign="top" width="140">
   <img src="http://www.kubat.nl/bld/UriGeller.jpg"/>
  </td>

 </tr>
</table>

<center>   

<object width="425" height="355"><param name="movie"
value="http://www.youtube.com/v/M9w7jHYriFo&rel=1"></param><param
name="wmode" value="transparent"></param><embed
src="http://www.youtube.com/v/M9w7jHYriFo&rel=1"
type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object>

<p/> If you want the full enchillada: here are four more videos on
James Randi and Uril Geller.

<p/>
<object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/zBEbfiaZTfc&rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/zBEbfiaZTfc&rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object>

<p/>
<object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/jp6Q-3VxNzM&rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/jp6Q-3VxNzM&rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object>

<p/>
<object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/jF05m_wrgi4&rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/jF05m_wrgi4&rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object>

<p/>
<object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/EMcg_6lj0SI&rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/EMcg_6lj0SI&rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object>

</center> 
</description>
   </item>
   <item>
    <title>Opt in for b2b spam</title>
    <link>http://www.kubat.nl/pages/blogaria/68#68</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 January 23rd was a historic day in the Netherlands. Our government
finally <a href="http://www.webwereld.nl/ref/rss/49546"
target="_blank">levelled rules on all unsollicited e-mail</a>:
previously, business-to-consumer spam required an 'opt-in'
(subscription) by the recipient. Spammers who only provided an opt-out
link in their mail would get fined. Unfortunately, when these rules
were introduced years ago, business-to-business spam was somehow overloooked.

</p> As of yesterday, the same rules apply to business-to-business
spam. If you want to receive spam, you have to request it - whether
you are a consumer, or act on behalf of a company. This might not seem
like a big deal, but in my opinion, it is. The website of the Dutch
Chamber of Commerce freely provides contact e-mail addresses of
companies, which are abused by b2b spammers. "Advertise on our radio
station!" "Buy cheaper DVD's!" "Would you like to reach 350.000
consumers at once?" Well, no more of that. The first mail spams that I
receive are going to be forwarded to the Opta, the Dutch telecom
watchdog.

<p/> Finally. 
</description>
   </item>
   <item>
    <title>Bokito Revisited</title>
    <link>http://www.kubat.nl/pages/blogaria/67#67</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td valign="top">

    Here's a short, personal update about <a
    href="http://www.kubat.nl/pages/blogaria/16#16">Bokito</a> and
    especially the glasses.

    <p/> Last holidays I was swapping funny stories with friends, and
    told about the famous glasses. The next day I got a little
    present.. I'm happy now.

   </td valign="top">
   <td width="360">
    <img src="http://www.kubat.nl/bld/MeAndBokito.jpg" width="360"/>
  </td>

 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Top Crossroads User</title>
    <link>http://www.kubat.nl/pages/blogaria/66#66</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Felix O. recently mailed me the usage data of their Crossroads installation.

<p/> The heaviest Crossroads user of the moment is a websearch
company, who at the time of writing this (January 2008) runs over 5
million page hits per day via Crossroads. They are requests for
dynamic pages, load-balanced using Crossroads' HTTP balancing. This is
on average 60 Crossroads requests per second flat rate, climbing to
approx. 250 per second. The same Crossroads instance also balances
300-500 database connections that carry approx. 50Gb of data. The
Linux box where Crossroads runs, is 50% idle.

<p/> Encouraging, or what? I'm also working on the 1.7x series of <a
href="http://crossroads.e-tunity.com" target="_blank">Crossroads</a>
which optimizes the HTTP processing of TCP streams. The load on
HTTP-related processing should be significantly lowered. 
 
</description>
   </item>
   <item>
    <title>World of Warcraft Dancing</title>
    <link>http://www.kubat.nl/pages/blogaria/65#65</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Yesterday I saw this <b>really great</b> vid on Youtube. It has
fragments of real life dancing (from movies or videos) and features
World of Warcraft characters dancing alongside.

<center>
 <object width="425" height="355"><param name="movie"
 value="http://www.youtube.com/v/066_q4DIeqk&rel=1"></param><param
 name="wmode" value="transparent"></param><embed
 src="http://www.youtube.com/v/066_q4DIeqk&rel=1"
 type="application/x-shockwave-flash" wmode="transparent" width="425"
 height="355"></embed></object>
</center>

I'm just wondering: how did this vid come to be?

<ul>

 <li> Either the person who made this, has no social life whatsoever. They've
 been matching real life movies with WoW characters until they got it
 right. Or I'm way off base? </li>

 <li> Or this was an inside job. Someone from Blizzard supplied a list
 of movies and videos that had been used as a basis for the avatars'
 dancing moves. That would've made the matching way easier. </li>

</ul>

In any case, I admire the quality of this vid. The avatars appear to
be dancing 'alongside' real characters. They're even dressed like the
real ones! And are the female elves way hot, or what? 
</description>
   </item>
   <item>
    <title>Justice dispensed better late than never</title>
    <link>http://www.kubat.nl/pages/blogaria/64#64</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The wheels of justice grind slowly, and ever so often they will grind
a black grain to dust, even when it's way due.  But better late than
never. Here are two examples that at least I find encouraging. Both
examples concern data exposure and privacy, two of my favorite
subjects.

<ol>

  <li> <b>TellSell</b> <br/>
  <div width="204" class="floatright">
  <img src="http://www.kubat.nl/bld/TellSellLogo.png"/>
  </div>
  
  TellSell <a href="http://www.kubat.nl/pages/blogaria/56#56">lost
  about 30.000 credit card data</a> because they failed to protect the
  data sufficiently. EMC, an European credit card clearing house,
  decided to cut them off. I suspect that the affiliated credit card
  companies were getting too much flak for fraudulent transactions.
  Anyway, last week, TellSell filed bankrupcy in the Netherlands.

  <p/> Quite perversely, TellSell's logo are (were?) two cogwheels
       that are intertwined, but for no reason whatsover. They don't
       really do anything useful, do they?

  <p/> Moral of the story: Get your data protection right, or roll
  over and die. Or in a broader sense: You may think that your primary
  business process is limited to selling kitchen knives. It's not. As
  soon as you start doing business over the Internet, your primary
  business process will extend to the whole palet of security issues,
  privacy, and what not. Better be prepared. Ignorance is not an excuse.

  <p/> </li>

  <li> <b>Hells Angels</b> <br/>
  <div class="floatright">
   <img src="http://www.kubat.nl/bld/HellsAngels.png"/>
  </div>
  
  A part of the legal proceedings against the Dutch Hells Angels
  were declared invalid. The Dutch General Attorney's office had tapes
  of illegal wire taps, and had been repeatedly warned against keeping
  such tapes. The tapes apparently held confidential information of
  conversations between suspects and their attorneys.

  The Dutch Justice Department had repeatedly warned the General
  Attorney's office, and had summoned them to stop this. When -again-
  tapes of such confidential conversations turned up in the files of
  the proceedings, the Justice Department declared the whole
  proceedings invalid.

  <p/> This was a huge blow to the Attorney's Office. Had the Hells
  Angels not violated many laws? Were they not true suspects of
  society-undermining activites? They might. But the Justice
  Department showed balls here: get with the program, or you don't
  have a case. Kudos for taking this stand! </li>

</ol>
 
</description>
   </item>
   <item>
    <title>Jeremy Clarkson and Identity Theft</title>
    <link>http://www.kubat.nl/pages/blogaria/63#63</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td valign="top">

   It seems that identity thieves have a sense of humour.

   <p/> A while ago there was a quite famous <a
   href="http://www.kubat.nl/pages/blogaria/56#56">loss of 25 million
   records of British families who are entitled to child benefits</a>,
   including bank account numbers. Jeremy Clarkson, BBC presentator
   and one of the guys behind my favorite car show "Topgear", didn't
   think it was quite such a big deal. "All you'll be able to do with
   them is put money into my account. Not take it out. Honestly, I've
   never known such a palaver about nothing." And he put his money
   where his mouth is - he published his bank account number and bank
   name.

   <p/> Only a few days later, he <a
   href="http://news.bbc.co.uk/2/hi/entertainment/7174760.stm"
   target="_blank">wrote</a>: "I opened my bank statement this morning
   to find out that someone has set up a direct debit which
   automatically takes 500 pounds from my account. The bank cannot
   find out who did this because of the Data Protection Act and they
   cannot stop it from happening again. I was wrong and I have been
   punished for my mistake."

   <p/> Jeremy, you're a gentleman for admitting that your original
   statement was false.

   <p/> Jeremy Clarkson continues: "Contrary to what I said at the
   time, we must go after the idiots who lost the discs and stick
   cocktail sticks in their eyes until they beg for mercy." Amen! And
   in the same vein: are we going to rethink our position on privacy?

  </td>
  <td width="194" valign="top">
   <img src="http://www.kubat.nl/bld/JeremyClarkson.png"/>
  </td>
 </tr>
</table>

 
</description>
   </item>
   <item>
    <title>Terrorism in the Netherlands</title>
    <link>http://www.kubat.nl/pages/blogaria/62#62</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td valign="top" width="250">
   <img src="http://www.kubat.nl/bld/Peugeot-207.jpg" width="250"/>
  </td>
  <td>

   The Netherlands are involved in an important fight. A battle even.
   We're not totally sure against whom, but we're very serious about
   it. <a href="http://www.nederlandtegenterrorisme.nl"
   target="_blank">The government informs us</a> that more than
   200.000 professionals are involved in this, day in day out,
   fighting...

   <p/>
   Terrorism. Fighting terrorism, you might ask? Yes, terrorism.
  </td>
 </tr>
 <tr>
  <td colspan="2">
   <p/>
   
   Have the Netherlands recently suffered terrorist attacks? Are the
   people frightened of things to come? Well no, not particularly. The
   only "terrorist" activities that we've had here, were in the
   1970's, when post-colonial second generation Indonesians,
   specifically from the island group the Molucs, decided that a fight
   for their right was appropriate. They hijacked trains in the
   Netherlands and occupied a school. They wanted a contry for
   themselves. It was a frightening time, and unfortunately, people
   got killed. Eventually, in typical Dutch tradition, everyone
   reconciled. The terrorists didn't get their own country, but were
   allowed to hold a memorial for their fallen comerades.

   <p/>
   So where does the current terrorist threat come into play?

   <p/>
   In the town of Delft, car mechanics discovered a bomb underneath a
   Peugeot, just as they were about to service the car. And this week
   a Peugeot blew up on a highway near Delft! The driver managed to
   get out of the car and was rushed to a hospital, with burn injuries
   to his legs. 

   <p/>
   Terrorism? Oooh!

   <p/> My imagination ran off with me. <br/>
   Senior terrorist: "Last week you learned to make car bombs. This
   week your assignment will be to blow up some cars." <br/>
   Junior terrorist: "Oh, I can't wait! What may I blow up? Some
   trucks that transport chemicals, or better yet, petrol or flammable
   substances? Or maybe government officials' cars?" <br/>
   Senior terrorist: "No, that's better left to the professionals. You
   need practice first. You will start by blowing up Peugeot 207's.
   <br/>
   Junior terrorist: "Awwww.. C'mon! Can't I go and blow up something
   serious?" <br/> 
   Senior terrorist: "No, and that's final. Next week we will evaluate
   your performance and discuss your further career." <br/>

   <p/>
   After a day or two, the news reached us that the victim was a drug
   peddler, who had apparently ripped off the Turkish mob during a
   deal. Alas, the 200.000 professionals who are fighting terrorism
   are still waiting for their moment to shine.

  </td>
 </tr>
</table>

    
</description>
   </item>
   <item>
    <title>The mind and bodysnatchers are among us</title>
    <link>http://www.kubat.nl/pages/blogaria/61#61</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 They are among us. They have been living among us for a long time, we
even can't be sure how long. But we finally have the proof.

<p/> They have been engaging in voodoo and zombie rituals in the
French Polynesian Islands, and we have unrefutable evidence. We now
know how they operate.. and how they turn us into mindless slaves,
meek as dogs on leashes, and how they then use our bodies for their progeny.

<p/> They are small, much smaller than we are. That's maybe why we
don't recognize them as our mortal enemies. They are fast and deadly, 
their weapons are poisons. First they will numb us with a poison
sting and patiently wait.. while we feel how we loose control
of our bodies, and realize that we are no longer able to defend
ourselves. Then they will administer a second poison sting, right into
our brain. Again they will patiently wait, knowing that they have
already won, while we loose control of our minds as well. Our bodies
continue to function: we breath, we look, we turn our heads - but without a
will, as if our bodies no longer belong to us, as if our bodies are on
autopilot. We have become zombies.

<p/> Their tactic is our worst fear: we are stripped from everything
that makes us 'ourselves', we are robbed of the control over our
bodies, as well as the control over our minds.

<p/> They are patient. They are precise. They are prepared.

<p/> Their nest will typically be nearby, ready for the grisly future
that awaits us.. All they have to do, is to drag us into it. We follow
them wherever they decide to take us, unable to resist. We are meek as
lambs on the way to the slaughterhouse.

<p/> Once in their power and in their nest, their purpose becomes
apparent. Without remorse they will lay their eggs into our bodies.
Their larvae will hatch and silently feast on the nutrients that we
provide. We are degraded into mindless organic hatcheries, nothing
more than a container of nutrients. Their larvae will grow and reach
maturity, and finally we will die, not even aware, not even thankful
that the ordeal is finally over.

<p/> Do you <a href="http://www.kubat.nl/bld/Wasp_movie_short.mpg"
target="_blank">dare to watch</a>?

 
</description>
   </item>
   <item>
    <title>Bruce Schneier and Hildo</title>
    <link>http://www.kubat.nl/pages/blogaria/60#60</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Yesterday I ran across two noteworthy sites that I'd like to share.

<p/> First, there's security guru <a href="http://www.schneier.com/"
target="_blank">Bruce Schneier</a>. He answered a user-submitted list
of questions for the <a
href="http://freakonomics.blogs.nytimes.com/2007/12/04/bruce-schneier-blazes-through-your-questions/"
target="_blank">Freakonomics</a> blog of the NY Times. A worthy read
with a treasure of links to related Bruce Schneier's work.

<p/> Bruce Schneier isn't only a crack in the technical sense (he
wrote the Blowfish and Twofish algorithms). I find that the most
interesting articles are the ones where he digs into psychological and
economical aspects of security. Read for yourself. Incidentally, his
blog comments are also available in podcast format (which comes out
monthly): a great passtime when in traffic jams.

<p/> On a lighter note: if you're Dutch speaking, be sure to check out
<a href="http://www.twolefthands.nl/" target="_blank">Hildo's
Egocentric Website (twolefthands.nl)</a>. The guy has huge glasses and an
even bigger beard, does his own metal work for his Harley, tries to
play the Banjo, and shares his insights on gourmet cooking with us.
Based on what one can read on his site, he's a happy camper..
 
</description>
   </item>
   <item>
    <title>Bye bye, good Christian soul</title>
    <link>http://www.kubat.nl/pages/blogaria/59#59</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td width="218" valign="top">
   <img src="http://www.kubat.nl/bld/mijter.gif"/>
  </td>
  <td valign="top">
   Yesterday, whilst bored in a traffic jam, I overheard an
   interview on the radio. They talked to Cardinal Simonis, our local
   representative of the Catholic God, who will vacate his seat on
   December 12th. They of course talked about his many years of service,
   the decline in the number of church visitors, the problems of
   our multi-cultural society, and what not.
   
   </p> Here are a few snippets that I thought I should share.
  </td>
 </tr>
</table>

<ul>

  <li> On the subject of dwindling influence of the Catholic church.
  Simonis: "No, the influence is not diminishing. Only last month we
  sent an open letter to many organisations in the Netherlands. The
  letter was very well received." Yeah, right, that's why I never saw
  it. Incidentally I asked some co-workers and friends, no-one saw the
  letter yet as e.g. a reprint in some newspaper. </li> 
 
  <li> On the subject of more and more nudity on TV. Simonis: "Yes, I
  am concerned and troubled about the ads for female lingeray. It's
  another symptom of the 'sexualisation' of our society." I kinda agree
  with the guy, though it's not really about lingeray. Shouldn't he be
  more troubled about trafficking, child porn and the such? That however
  doesn't seem to bother him. I wonder whether the guy's aware of such
  things at all - I wouldn't be surprised if he only sees the poster ad
  for lingeray because it's on the way to his office. </li>

  <li> About the level of education in the Netherlands: "Yes, well, I
  am an alpha-type myself." [Red: In Holland the school subjects are
  loosely divided into 'alpha' (languages, history etc.) and 'beta'
  (technical stuff, math, physics, chemistry, biology etc.).]
  "Beta-sciences are important, technology-wise and for the the
  quality of living. But all 'real' thinking is course done by the
  alpha people." Is this guy for real? </li>

  <li> Later on, still about the dwindling numbers of church-goers in
  the Netherlands. Simonis: "Yes, the counts of visitors have been
  declining." Well thank God that the influence of the Catholic church
  is still sky high (see above), despite that fewer people visit the
  sermon. Simonis, cont.: "But the Catholic church is strong as ever
  in Africa and South America." Interviewer: "So do you think there's
  a chance that the new cardinal will be African or South American?"
  Simonis, somewhat condescending: "No, Miss, don't you worry. That's
  not going to happen." </li>

</ul>

As I was listening to the interview I didn't even get excited or
disgusted or the like - in fact I was surprised by the lack of
emotion. I just felt a slow dumbness descend over me.
 
</description>
   </item>
   <item>
    <title>Confusing mail message</title>
    <link>http://www.kubat.nl/pages/blogaria/58#58</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I'm confused. They're mailing me personally, so it's gotta be
important. But I can't make heads or tails of it! What did I win? How
many rubles? How do I get in contact with them to claim my prize?
Where do I download their <i>viewer.exe</i> which of course is not a
Trojan but instead will do something fantastic that I'm always
dreaming about? Are the 17 steps mentioned below the sure-footed way
to unspeakable riches and personal happiness?

<p/> <b>Update:</b> I'd asked for some translation help, and got it
pretty fast from <a href="http://eddie.niese.net"
target="_blank">Eddie</a>. Ed doesn't speak Russian any more than I
do, but he's a handy sort of chap and knows of many sites that can
translate stuff. E.g., <a
href="http://www.google.com/translate_t?langpair=ru|en"
target="_blank">Google Translate</a> can do it.

<p/> It seems they're trying to get me to participate
in a symposium on the legal aspects of leasing stuff in Russia.
Bummer. I hoped that they'd inherited an obcene amount of rubles and
were trying to get it out of the country via my Dutch account.

<pre>
From: 	 ogl@bottledblessings.com
Subject: Регистрация договора аренды
Date: 	 December 3, 2007 2:24:30 PM GMT+01:00

Здравствуйте!

Пришлашаем Вас принять участие в однодневном семинаре на тему:
Договор аренды. Правовые, налоговые и бухгалтерские аспекты. Налоговые
преимущества договора аренды. Конкретные способы минимизации налоговой
нагрузки с учетом позиции Минфина.

(Письма Минфина РФ, ФНС РФ, Арбитраж)

Семинар пройдёт 21 декабря / 2007, г. Москва

Программа: 

1. Виды договоров аренды . Требования закона к форме договора аренды и
его государственной регистрации. Последствия его несоблюдения.
Существенные условия договора.
Диспозитивные и императивные нормы.
2. Объекты аренды. Права третьих лиц на объекты аренды.
3. Правовое положение сторон договора аренды.
Сохранение договора аренды в силе при смене арендодателя.
4. Возмездность договора аренды.
Понятие возмездности договора аренды. Арендная плата: метqоды
определения и составляющие цены арендной платы. Формы арендных
платежей. Взаимозачет и иное удовлетворение требования кредитора по
возмездному договору аренды. Изменение цены арендной платы.
5. Сроки в договоре аренды.
Определенный и неопределенный срок аренды. Предельный срок договор
аренды. Сроки внесения арендной платы. Последствия их просрочки.
6. Расторжение договора аренды.
Расторжение договора аренды по взаимному согласию сторон. Расторжение
договора в одностороннем порядке. Расторжение договора по требованию
арендатора. Возмещение убытков при расторжении договора. Обзор
судебной практики оснований расторжения договора аренды.
7. Прекращение и возобновление договора аренды.
Гибель арендованного имущества. Истечение срока действия договора.
Выкуп арендованного имущества в течении срока действия договора. Иные
основания прекращения договора аренды. Возобновления договора аренды
по согласию сторон. Преимущественное право арендатора на заключение
договора на новый срок. Возобновление договора аренды при замене
стороны обязательства.
8. Налоговые преимущества договора аренды.
9. Регистрация договора аренды и налог на прибыль.
Позиция Минфина РФ , ФНС России и арбитражных судов.
10. Субъекты арендных отношений. Их права и обязанности
10.1.. Арендодатель. Его правовой статус. Предоставление имущества
арендатору. Документальное оформление передачи.
Правовые и налоговые последствия не оформления передачи арендуемого
имущества. Недостатки арендуемого имущества и их обнаружение
Бухгалтерский и налоговый учет Арендодателя с учетом изменений ,
внесенных Федеральными законами 58-ФЗ и 119-ФЗ:
передача имущества в аренду , учет арендной платы ( НДС, налог на
прибыль), начисление амортизации по О.С., переданным в аренду , ремонт
переданного в аренду имущества , оплата коммунальных услуг, выкупная
цена .
10.2. Арендатор. Его правовой статус.
Бухгалтерский и налоговый учет Арендатора с учетом изменений ,
внесенных Федеральными законами 58-ФЗ и 119-ФЗ :
арендные платежи и проблемы вычета НДС по коммунальным расходам ,
ремонт арендованного имущества, условия выкупа арендованного имущества
10.3. Ремонт арендованного имуществ с позиции арендодателя и арендатора.
10.4. Арендная плата и "коммунальный" учет. Противоречивая позиция Минфина РФ.
11. Оптимизация налогообложения при учете расходов на содержание и
улучшение арендованного имущества, ремонтных и коммунальных расходов
путем включения в договор контрактных оговорок
12. Договор аренды в условных единицах
13. Субаренда.
14. Аренда федерального и муниципального имущества. Особенности
исчисления м вычета НДС.
15. Аренда земельного участка под строительство. Позиция чиновников.
16. Договор безвозмездного пользования (ссуды). Налоговые последствия
для ссудополучателя..
17. Обзор практики рассмотрения арбитражными судами споров по договорам аренды .

Продолжительность обучения: с 10 до 17 часов (с перерывом на обед и кофе-паузу).
Место обучения: г. Москва, 5 мин. пешком от м. Академическая.
Стоимость обучения: 4900 руб. (с НДС). 
(В стоимость входит: раздаточный материал, кофе-пауза, обед в ресторане).

При отсутствии возможности посетить семинар, мы предлагаем приобрести
его видеоверсию на DVD/CD дисках или видеокассетах (прилагается
авторский раздаточный материал).

Цена видеокурса - 3500 рублей, с учетом НДС.

Для регистрации на семинар необходимо отправить нам по факсу или
электронной почте: реквизиты организации, тему и дату семинара, полное
ФИО участников, контактный телефон и факс.

Для заказа видеокурса необходимо отправить нам по факсу или
электронной почте: реквизиты организации, тему видеокурса, указать
носитель (ДВД или СД диски), телефон, факс, контактное лицо и точный
адрес доставки.


Получить дополнительную информацию и зарегистрироваться можно:
по т/ф: (495) 543-88-46
по электронной почте: solon@besttraining.ru

Так же Вы можете посетить другие наши программы:
11 декаюря: Новый закон "О рекламе"
13 декабря: Автомобиль в вашей организации
17 декабря: Сложные вопросы признания "прочих" расходов в 2007 году
24 декабря: Торговые организации. Бухгалтерский учет, налогообложение.
26 декабря: Основные средства - бухгалтерский и налоговый учет
</pre>
 
</description>
   </item>
   <item>
    <title>Medion MD 85276 reviewed</title>
    <link>http://www.kubat.nl/pages/blogaria/57#57</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 If you're into gadgets and unexpected peripherals, check out Eddie's
review of the <a
href="http://eddie.niese.net/20071129/new-digital-notepad-gadget/"
target="_blank" >Medion MD 85276</a> digital notepad. He bought it at
a Dutch supermarket, where one can often find el-cheapo electronics -
and sometimes even pretty good stuff. The review has also very useful
links to software which converts the notepad files from its closed TOP
format into SVG, which is open enough to be further handled.

</p> I can't wait to see Eddie in action during meetings, toting his
electronic scratch pad, and e-mailing images of his notes just seconds
after meeting closure..
 
</description>
   </item>
   <item>
    <title>Recent cases of data exposure</title>
    <link>http://www.kubat.nl/pages/blogaria/56#56</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 There have been some shocking cases of data exposure the last few
weeks. Just to name two: 

<ul>

  <li> The credit card clearing house EMC (who handles transactions
  for Visa, Mastercard and I think a few more credit card companies)
  decided not to business 
  anymore with TellSell, the guys who'll send you 20 free knives if
  you order their set of stick-free pans. Reason: TellSell didn't
  sufficiently protect the credit card data of their customers,
  leading to too many fraudulent transactions. Apparently customer
  data were stolen via TellSell's site, and re-used on other sites
  by data identity thieves. </li>

  <li> The top story: the British government "lost" 25 million records
  of families entitled to child benefits. Each record would hold names
  and account numbers. It seems that the data were backed up or copied
  unto two CD's, and the CD's somehow got lost. It's not clear whether
  this case is a theft; the CD's may still show up (did they check
  their car trunks? It's where I usually find stuff that I've
  "lost"). </li>

</ul>

Anyway, these news bits somehow strangely fall into place, regarding
my previous posts of the <a
href="http://www.kubat.nl/pages/blogaria/52#52">trustworthiness of
governments or organisations</a>, and of the <a
href="http://www.kubat.nl/pages/blogaria/53#53">necessity to keep data
around</a>.

<p/> In the case of the data exposure in Britain, I argue that there will
always be f**kups due to human error. And even if we could eliminate
the human factor: who's to guarantee that the technology of data
protection is sufficient to prevent data exposure? It would obviously
be best if the data were not in readable format anyway. Now I can see
that the British "Ministry of Family Affairs" (there is no such thing,
but bear with me) needs to know who's entitled to child benefits. They
would need a list of families. But do they need the account numbers
too? Why were those account numbers not stored separately, in a list
maintained by the "Ministry of Finance"? The two lists might've been
linked by keys based on non-reversible hash algorithms. If this had
been the case, then the impact of the data exposure would've been far
less: only a list of families would have leaked, without sensitive
account data.

<p/> In the case of TellSell, I argue that this organisation doesn't
need to keep credit card data at all. They only need a list of website
visitors, and for each visitor, they need to construct a
non-reversible hash value of credit card data.  When appropriate, the
hash value sent to EMC for payment purposes. Oddly enough, I wrote
about using <a href="http://www.kubat.nl/pages/blogaria/53#53">hash
values for this purpose</a> just two weeks ago.

<p/> In both cases, technological or human errors led to data
exposure. But more fundamentally: the way that the data were stored
was flawed when looking at the matter from a security perspective.

<p/> In most cases software will be designed and built so that
it's delivered fast and cheap: meaning here: "store all data you can
yourself, instead of delegating data ownership where it belongs."
Delegating ownership would of course mean that complex algorithms of
non-reversible hashes would need implementing, that transmission of
data would involve transmitting such hashes and verifying them, and so
on. Security-wise a good concept, but definitely more expensive than
the current approach of least resistance.

<p/> I'm just wondering what will happen in the evaluation of these
cases. I'm sure that the poor guy who backed up 25 million records
onto two CD's and then misplaced them, will get some punishment. His
boss will also suffer some consequences. But the IT architect who
designed this? I'm pretty confident that he'll still be considered an
expert who did a fine job. The same goes for TellSell. They will
rigorously review their website security features and probably axe a
few scapegoats, but they will never question the overall design. 
</description>
   </item>
   <item>
    <title>Bayes bites</title>
    <link>http://www.kubat.nl/pages/blogaria/55#55</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 As I'm re-reading my notes on privacy and huge data collections, a favorite
story springs into mind. It's about Baysian statistics. The idea for
the text below is from John A. Paulos' book <i>A Mathematician Reads
the Newspaper</i> (I can highly recommend reading this).

<i> <p/> Imagine a city of 10 million people, where a brutal crime is
committed by one of the citizens. Furtunately, the killer left their
fingerprints at the murder scene, so the detectives have a perfect
starting point for their investigations.

<p/> Another fortunate thing is that the City has collected the
fingerprints of all citizens in a huge database, with the purpose of
speeding up and helping the fight against crime. Great! One might
expect that the murder will be solved swiftly...

<p/> So the detectives fire up their systems and let the computer
compare the crime scene prints against the set of the prints of all
citizens. The computers start crunching numbers, everyone holds
their breath, and.. finally.. after 3 weeks of humming, the computer
finds a match. A suspect is arrested and brought to trial.

<p/> The court hears all involved parties, and all subject matter
specialists. Just to be sure of the evidence, the judge asks an
expert: "How good is that fingerprint matching system?" The expert
answers: "Your honor, it's the newest-bestest system one can have, all
singing and dancing. The chance of error is very small indeed: it will
correctly identify a fingerprint in 99.9999% of the cases! There's
a chance of only one in a million that the machine says it's a match
while in fact it isn't."

<p/> The jury is convinced. Despite the fact that the suspect
continues to plea not guilty (but hey, that's to be expected), a
guilty verdict is returned. The jurors' motivation is: "The defendant
simply must be the one who did it. Why, there machine is almost
error-safe! The chance of a bad decision are only one in a million.
That's good enough for the court, We, the jury, are convicting the
defendant."  </i>

<p/> The truth here is that the suspect probably didn't do it. If the
fingerprint maching machine makes an error once in a million
comparisons, then statistically it would spit out 10 suspects, since
there are 10 million citizens. The chance that any randomly chosen
suspect who is identified by the machine has committed the crime, is
therefore 10%. The chance that the John Doe who was arrested and
convicted is actually not guilty, is 90%.

<p/> The error that was made by the jurors is a typical one. The "one
in a million" error chance suggests that the fingerprinting method is
pretty accurate. Which it may or may not be - but in any case, that's
not the question here. Bayes described his theorem using the following
phrasing: "What are the odds that X happens, <b>given the fact that Y
is already observed</b>". The "given that" clause is paramount: the
jurors should have asked themselves, "what are the odds that the
defendant is not guilty given the fact that his fingerprints
matched".
The answer to this question is straight forward: we expect
10 people's fingerprints to match, and only one of them is the perp -
so there's a 90% chance that the defendant is not guilty. The
given-that clause will typically decrease the size of the reference
population by selecting out a group with an already known factor.

<p/> I always try to illustrate this for myself as a matrix of
categories and (sub)populations. We have two factors here: (a) A
person is guilty or not, and (b) a person's fingerprints match or they
don't. These categories can be illustrated in a simple 2x2 matrix,
with a third row and column for totals:

<center>
<table>
 <tr>
  <td></td>
  <td bgcolor="gray">Guilty</td>
  <td bgcolor="gray">Not Guilty</td>
  <td bgcolor="gray">Totals</td>
 </tr>
 <tr>
  <td bgcolor="gray">Fingerprints match</td>
  <td bgcolor="lightgray" align="right">1</td>
  <td bgcolor="lightgray" align="right">9</td>
  <td bgcolor="lightgray" align="right">10</td>
 </tr>
 <tr>
  <td bgcolor="gray">Fingerprints don't match</td>
  <td bgcolor="lightgray" align="right">0</td>
  <td bgcolor="lightgray" align="right">9.999.990</td>
  <td bgcolor="lightgray" align="right">9.999.990</td>
 </tr>
 <tr>
  <td bgcolor="gray">Totals</td>
  <td bgcolor="lightgray" align="right">1</td>
  <td bgcolor="lightgray" align="right">9.999.999</td>
  <td bgcolor="lightgray" align="right">10.000.000</td>
 </tr>
</table>
</center>

<p/> I think that this representation nicely summarizes all of the
above, though admittedly it takes some time to getting used to such
illustrations. The bottom line of this example is that large data
collections (such as a database of fingerprints of all citizens)
may not be useful at all in determining culprits when used as the sole
source of information. On the contrary: "very precise" methods and
large datasets may look good but produce very bad results. Every
method, however precise, has a chance of producing false positives
(see also the <a
href="http://www.kubat.nl/pages/blogaria/51#51">Schiphol</a>
entry), and even a small chance of false positives will yield
quite large numbers of distinct cases when the reference population is
large enough. 

<p/> As a last remark. Incase you're wondering how precise fingerprint
comparisons are: current methods are approx. 98.5% accurate or better,
which is way less than the hypothetical 99.9999% used in this
example. That's another reason why I think that <a
href="http://www.kubat.nl/pages/blogaria/54#54">Japan's plans to
fingerprint all foreigners</a> make no sense.
 
</description>
   </item>
   <item>
    <title>Japan starts fingerprinting foreigners</title>
    <link>http://www.kubat.nl/pages/blogaria/54#54</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen on <a href="http://yro.slashdot.org/article.pl?sid=07/11/19/0436218" target="_blank">slashdot</a>:

<p/>
<i>"If you're planning to visit Japan sometime in the near future, you
should be aware of the welcome you'll get. Last year, Japan's
parliament passed a measure requiring foreigners to submit their
fingerprints when entering the country. The measures, which apply to
all foreigners over 16 regardless of visa status, take effect
tomorrow. The worst part: the fingerprints are stored in a national
database for an "unspecified time", and will be made available to both
domestic police and foreign governments."</i>

<p/>
There goes the personal privacy again. Thanks to such measures, we're
forced to place an implicit trust in organisations or countries that
we don't really know. Also we're forced to extend this trust into the
future, since Japan will store the fingerprints "for an unspecified
time". And what's even scarier, we're forced to trust the Japanese
authorities "by proxy". We have no idea who the "foreign governments"
are that Japan is willing to share the data with.

<p/>
I wrote <a href="http://www.kubat.nl/pages/blogaria/51#51">earlier</a>
about a similar idea of the European Union, concerning storing flight
movement data. That idea didn't make sense to me, and neither do the
Japanese plans. I still think that

<ul>

  <li> The "ownership" of my personal data lies with me, unless proven
  otherwise. </li>

  <li> No-one should be forcing me to trust anyone for an unspecified
  time. You might ask me to trust you <b>now</b>, but you can't expect
  me to state that I'll be trusting you in ten years! </li>

  <li> In the end, such measures will make no sense at all, they
  simply won't be effective. Not even historical data indicate that
  this measure should help: no terrorist attack in Japan ever was
  committed by foreigners. </li>
</ul>

<p/>
Trust by proxy in a time warp, what a bitch.

 
</description>
   </item>
   <item>
    <title>Privacy, Yahoo and the Strange World</title>
    <link>http://www.kubat.nl/pages/blogaria/53#53</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 It's a strange, strange world. A while ago, two Chinese bloggers were
convicted after Yahoo had turned over their identity data to the
Chinese authorities. The prison sentences in China are not for the
feeble of heart: one of the bloggers will spend 10 years in jail for
speaking out for democracy on his blog, and I'm not sure what the
sentence of the other blogger is.

<p/> I suspect that Yahoo are eager to do business in China, which
they see as one big emerging market, and hence are forced to comply
with local regulations. The sentencing of the two bloggers is harsh
and conter-democratic, we will all agree - but did Yahoo do anything
wrong, in the strict sense of the applicable law? I don't know.

<p/> And neither do the US authorities. Yahoo were summoned to a hearing
in Washington DC, where two of their US-based executives were put to
the test: could Yahoo have known what the Chinese authorities were
going to do to the two bloggers, as they were turning over the identity
data? If so, could they have avoided handing over the data? Could they
have complied with the Chinese regulations in a "less strict" way?
What does that mean, "yeah, comply with the Chinese authorities, but
feed them bullshit"? 

<p/>
It's a strange world. Yahoo and other companies are required by law to
retain data, and are required to turn over such data to the
authorities when requested to do so. However, it appears that there
are exceptions to this rule:

<ul>

  <li> The rule doesn't need to be adhered to strictly when applied to
  foreign governments. </li>

  <li> Actions that follow from this rule will come under scrutiny
  when the public outcry is loud enough. </li>

</ul>

How hypocritical is that? The very same US authorities have
implemented a "no fly list" which is already shown to
malfunction: once you get on it, you won't be able to fly, and getting
off the list seems almost impossible. The very same US authorities tap
all sorts of communications and retain such data, fishing for
information on undesirable activities. Our own Dutch authorities
require ISP's to retain Internet-activity related data for 18 months
for the same purpose. Why? Because it may come in handy some
day. Dutch Telecom providers have data stating which mobile phones
connect to which ground stations - making it possible to track the
movements of the phone owners. Why? Because they can.

<p/>
So as I'm surfing the web, making phone calls, and doing all sorts of
things, I'm leaving a trail of data. I consider such data very
personal: they are <b>my</b> actions, which are private. If you want
to know what I did and when, ask me - and if I think you're entitled
to know, then I'll tell you. This doesn't work the other way 'round!
You're <b>not</b> entitled to dig through my personal data to see if
you can find anything that's of interest to you, whether your interest
has a legal perspective, a commercial perspective or whatever. It's a
matter of principle.

<p/> So, which organisations can I trust to handle my data trail in a
careful and responsible
way? The Dutch state? The <a
href="http://www.kubat.nl/pages/blogaria/51#51">European Union</a>?
The Chinese or US 
authorities? My telecom provider? My ISP?

<p/> My data trail is just too wide and too fragmented to enumerate
whom I can trust and whom not. As far as I'm concerned, there is only
simple common sense here: <b>don't retain my data</b>!

<p/> Here's how I think it should work.

<ul>

  <li> To my telecom provider: "When my mobile phone connects to some
  ground station, don't store such data on a per-connection basis. If
  you need to know the load of a given ground station, use a counter -
  not separate connectivity entries that are later analyzed." </li>

  <li> To my ISP: "Don't store my IP address with the URL's I
  visit. Don't store the mail headers of my incoming or outgoing
  mail. You don't need such data. If you bill me for bandwidth usage,
  simply store counts of upstream and downstream transfers." </li>

  <li> To my forum site operator, where I regularly post: "Don't store
  my IP address. I know you need some measure to block addresses
  when people post offensive material, but you can achieve this by
  storing e.g. a SHA-2048 hash of the IP address. This can be checked
  when someone connects to the forum, but <i>a posteriori</i> it is
  harder to 
  reverse this to a physical address. If a forum entry isn't flagged
  offensive for say 3 days, then remove the associated data where the
  hash of the poster is stated."

  <li> To my authorities: "Don't force my telecom provider, ISP, forum
  operator and others to store my private data. There is no guarantee
  that they are trustworthy. Even if we all agree that they're OK
  today, who knows how they will be in say 5 years from now? If you
  need to investigate me for e.g. illegal activities, get a court
  order, and start tapping my actions. Avoid situations where
  investigations can be run by sifting through existing data." </li>

  <li> To all of the above: "Rethink your point of view. At the moment
  it's OK to store private data, as long as you do it in a 'secure'
  way (whatever that may be - usually you have to appear to be making
  some effort so 
  that the data don't get out on the street). That's not the way to
  look at this 
  matter: rather, storing data should not occur unless absolutely
  necessary (e.g. my bank needs to know who I am). In all other
  situations, storing private data should be discouraged and even
  illegal!" </li>

</ul>

I know, this is oversimplifying things. But I still feel that the
general principle applies. You get the idea.
 
</description>
   </item>
   <item>
    <title>Privacy, Fall through algorithms, and Securing data</title>
    <link>http://www.kubat.nl/pages/blogaria/52#52</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I was discussing data privacy with my good buddy &amp;
collegue <a href="http://eddie.niese.net"
target="_blank">Eddie</a>. We were talking about the idea of hashing
sensitive information and storing the hash, instead of storing the
actual plain-text information - an idea that I suggested in my
previous note on <a
href="http://www.kubat.nl/pages/blogaria/53#53">Yahoo and data
privacy</a>. Is storing hashes instead of plain data feasible? When
can it be used, and when not? Our discussion prompted me to elaborate
a bit. 


<h2>What's a hash value anyway?</h2>

<p/> The principle works as follows. One can convert text to a value
by chopping the text into chunks and feeding them into some algorithm
which is non-reversible. That means that if you have the text, you can
compute the value - but not the other way 'round.

<p/> Imagine the following hash function: <i>If you want to compute
the hash value of a name, then take each letter of that
name, where a=1, b=2 and so on, and add these values. The result is
the hash of that name.</i> This very simple hash function illustrates
the concept: "karel" would become 11+1+18+5+12=47, while "eddie" would
become 27. But knowing only the number 47, it would be impossible to
reconstruct my first name. So the algorithm is truly one-way.


<h2>What good is storing a hash instead of the original data?</h2>

<p>So based on this algorithm, one could distinguish two names
without actually knowing them, but only knowing the hash. E.g., let's
say that both Eddie and I register at some website. I am mainly
interested in music and build up my profile accordingly, while Eddie
is interested in tech news stories. Now let's say that the website
owner is so privacy-aware that he decides not to store the usernames
in a database, but only the hashes. I can still log on using "karel"
and Eddie can log on using "eddie", but the first thing the website
will do, is convert my name to "number 47" and Eddie's to "number
27". Then the website looks up a personal profile based on the hash
number, and shows corresponding data on the site. So profile number 47
will display playlists of music, and profile number 27 will display
the latest tech news. The trick here is that the actual user name only
exists on the login page, where I enter "karel" and Eddie enters
"eddie". Beyond that login page, the user name no longer exists, 
only the hash!

<p/> No problems so far. But what is it good for? Well, one important
aspect is, that my username is not stored in the site's list of
profiles. So a malevolent sysop there cannot get at my username and
log in using my account! Since only number "47" is known there, the
malevolent sysop has no way of knowing that he must type "karel" to
steal my identity.

<p/> But wait! This hash algorithm isn't too safe, is it? Number 47
can also be constructed using four j's (four times 10) and one g
(7). So user name "jjjjg" would also access my profile. And what if my
evil twin Lerak decided to register? He would also hit the same hash!

<p/> Accidentally hitting the same hash is called a
'collision'. Obviously a good hash function should not be only
one-way, but should also avoid collisions. There are very good hash
functions out there, such as the SHA family. However, none of these
are guaranteed to avoid collisions. 


<h2>Is there a practical application for this?</h2>

When I purchase items over the Internet, I often use my last name and
account number for billing. The account number in the Netherlands
consists of nine digits (eg., 123456789). I enter the name and account
number at the site where I'm purchasing an item, and the site then
connects to my bank to see if my balance is sufficient for the
transaction. Furthermore the site will surely store my last
name and account number, so that I don't have to retype it during a
next purchase.  They'll do anything to improve the "user experience"
and to entice me into visiting them again.

<p/> Two things are happening here: One, when I'm purchasing something
for ten euro's, the site asks my bank: "Is the balance of Kubat, with
account number 123456789, sufficient for a transaction of 10 euro's?"
Two, the last name Kubat and the account number 123456789 are stored
in some database of the site.

<p/> There is a number of dangers lurking here. First, someone may be
eavesdropping on the chitchat between the site and my bank. They can
find out that the combination Kubat/123456789 is valid for making
purchases, and start making purchases in my name! Second, any
malevolent employee of the site can find this in the site's database
and also misuse my identity for their profit. 

<p/> Obviously I don't want that to happen. So we can take a number of
measures - e.g., secure transactions between the site and my bank, and
restrict database access for all but a few site employees.
Unfortunately, however well designed the security measures may be,
there will always be ways around them. And there is still the basic
question - do the data <b>need</b> to be there in the first place?

<p/> So, why don't we use hashes instead of plain text data?

<ul>

  <li> The hash512 value of my last name "Kubat" is
  UlieNqKVJFYPlgu7ZAMUl0J5SG5ZV7nKtF9AK+fuuV/K3uljp0Glj2CyUFvC3N1GCV7SgxBmxkTOmCM+EeIGeA. </li>

  <li> When I log onto the site, I state my last name just once - on
  the login page. Beyond that, my last name just isn't available
  anymore, only the above hash. </li>

  <li> The hash of my account number "123456789" is
  2eZ2LdHI6vbWGzxhkvxAjU1tXxF20MKRabwk5xw/J0rSf81YEbMT1oH35V7ALXPUmclUVba1u1A6z1dPuo/+hQ. I'd
  have to enter my account number just once, when making the first
  purchase. AFter that, the site's database would store that "Person
  UlieNqKVJFYPlgu7ZAMUl0J5SG5ZV7nKtF9AK+fuuV/K3uljp0Glj2CyUFvC3N1GCV7SgxBmxkTOmCM+EeIGeA
  has account
  2eZ2LdHI6vbWGzxhkvxAjU1tXxF20MKRabwk5xw/J0rSf81YEbMT1oH35V7ALXPUmclUVba1u1A6z1dPuo/+hQ". </li>
  
  <li> When I purchase an item, the site would ask my bank: "Does person
  UlieNqKVJFYPlgu7ZAMUl0J5SG5ZV7nKtF9AK+fuuV/K3uljp0Glj2CyUFvC3N1GCV7SgxBmxkTOmCM+EeIGeA
  with account
  2eZ2LdHI6vbWGzxhkvxAjU1tXxF20MKRabwk5xw/J0rSf81YEbMT1oH35V7ALXPUmclUVba1u1A6z1dPuo/+hQ
  have a balance high enough to cover ten euro's?" </li>

  <li> My bank cannot reverse the supplied hashes to my name and
  account number; no-one can. But that's not necessary! My bank has a
  full list of customers and account numbers, They can pre-generate
  lists of hashes, and compare the two hashes that the site sends with
  their list to find my data. </li>

</ul>

Much better. Since the hashes aren't reversible to values, the
security risks have magically disappeared. But what about collisions?
Fortunately we are quite able to verify whether collisions occur. They
don't - each account number, ranging from 00000000 to 99999999 yields
its own unique hash.

<p/> And consider the following real-life situation. Many people
purchase items over the Internet and pay with their credit card. Each
transaction needs to be verified with a credit card company, where a
website might ask: "Is credit card holder A. Smith, with card number
1111222233334444 and verification code 123 and expiry date 02/10, good
for 20 dollars?" Any malevolent person only needs to get hold of these
data; once they have them, they are free to roam Internet sites and
purchase items using Smith's stolen identity.

<p> In contrast, imagine that the identifying data were a hash of the
combined values. In this case we could build up one long identifier,
consisting of "Smith,1111222233334444,123,02/10", compute the hash
(which is incidentally
"svzW3IjYHVr+sFj85FVXyZmMHrtcPMSJdZoTb9BXOjSfoEOdfZYeGYjSlMCbBcaPheYS1yiIMqu7ox+ICxjoIw")
and use that -again- in the following way:

<ul>

  <li> The hash would be computed just once, when the user registers
  at the site. After that, the original data would be discarded, and
  only the hash would be stored in the site's database. </li>

  <li> Verification of the transaction for 20 dollars would only
  transmit the hash, not the separate data. </li>

</ul>

All wannabe identity thieves who are looking for a quick buck: good
luck extracting the separate name, credit card number, verification
code and card expiry date from this hash.


<h2>So where and how can this approach be used?</h2>

The hash approach is suitable for all situations where a requestor
asks some central service a question concerning a person, or indeed,
anything that's identified by some data, such as in the previous
examples. The approach is <b>not</b> suitable in situations where a
requestor asks a generic question without supplying an identifier.

<p/> So for example, if websites were allowed to ask a credit card
company: "Give me a list of all your customers whose balance is high
enough to make a $20 purchase", then this approach couldn't be used -
there is no "identifier" in the question to hash. Furtunately, this
isn't a request that's allowed by the credit card companies (one may
hope).


<h2>Is this appraoch in use?</h2>

Personally, I haven't heard of it. Except for the fact that passwords
are stored in encrypted format; the encryption routine being a one-way
non-reversible algorithm. That's why you can't phone the helpdesk and
ask, "what is my password again, I lost it". The helpdesk guys don't
know, and they have no way of finding out. All they can do is reset
your password to some value that you can use for your next login. The
password storage methodology is so common that I wonder why the same
concept hasn't been applied to other privacy-sensitive data.

<p/> Will the approach ever be used? One may hope so, I don't see any
obstacles, only benefits. Well there is of course one obstacle -
websites and credit card companies would need to change their systems
to conform to the new way. This won't ever happen unless someone tells
them to. As I stated <a
href="http://www.kubat.nl/pages/blogaria/53#53">previously</a>:
storing private data should be prohibited, unless it is absolutely
necessary and there's no other way. That would be a good incentive!


<h2>Perl snippets for the playful</h2>

If you want to play around with the algoritms, below are a few Perl
snippets that I used when writing this.

<p/>Here is the "idiotically simple" hash algorithm.
<pre>
#!/usr/bin/perl

use strict;

# ihash - idiotic hash
# --------------------

# Check the command line.
die ("Usage: ihash name(s)\n") if ($#ARGV < 0);

# Show hash all arguments.
for my $n (@ARGV) {
    print ("$n: ", hash($n), "\n");
}

# The hash function
sub hash ($) {
    my $n = shift;
    my $h = 0;
    for my $c (split ('', $n)) {
	$c = lc($c);
	$h += ord($c) - ord('a') + 1;
    }
    return ($h);
}
</pre>

<p/>
Here's a short script to display sha512 hashes. You'll need the Perl
module Digest::SHA to make this run.

<pre>
#!/usr/bin/perl

# sha512 - displays the sha512 hash of all arguments

use strict;
use Digest::SHA qw(sha512_base64);

# Check the command line
die ("Usage: sha512 strings\n",
     "Displays the sha512 digest of all strings.\n") if ($#ARGV < 0);

for my $str (@ARGV) {
    print ("$str: ", sha512_base64 ($str), "\n");
}
</pre>

<p/>
I verified that Dutch account numbers between 000000000 and 999999999
do not collide when hashed using sha512. Here's now.

<pre>
#!/usr/bin/perl

# sha-accnr-checker
# If we sha512-encode Dutch account numbers (which have 9 digits),
# will we encounter collisions?

use strict;
use Digest::SHA qw(sha512_base64);

# Make the output unbuffered
$|++;			   

# Hash of seen digests
my %used;

for my $nr (0..999999999) {
    # Pad account number to 9 positions, compute the digest
    my $acc = sprintf ("%9.9d", $nr);
    my $dig = sha512_base64 ($acc);
    
    # Stop if there's a collision
    die ("\n$acc conflicts with $used{$dig}\n",
	 "both yield sha512: $dig\n") if ($used{$dig});
    
    # Store digest since we've now used it
    $used{dig} = $acc;

    # Show a ticker so we see what's going on
    print ("\r$acc") if (! ($nr % 10000));
}

# All done
print ("\nno collisions detected\n");
</sha>
 
</description>
   </item>
   <item>
    <title>European airlines to retain data</title>
    <link>http://www.kubat.nl/pages/blogaria/51#51</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today on <a
href="http://yro.slashdot.org/article.pl?sid=07/11/07/0351224"
target="_blank">Slashdot</a>:

<p/>
<i>[The EU] are contemplating requiring all 27 member states to
collect data on airline passengers and to retain it for up to 13
years. [...] The proposal is part of an anti-terrorism package that
also includes tighter laws to control hate speech and bomb-making
instructions.</i> 

<p/> I find such news bits somewhat scary. Actually I find them very
disturbing. For me, this is first of all an invasion of privacy. This
privacy argument is unfortunately quite hard to explain to others. The
counter-argument that is presented most often, is: "Why would you
oppose? If you have nothing to hide, then this shouldn't bother you,
should it?" My gut feeling however says something different: Why
should anyone care where I travel and when?

<p/> But I think that there is an even stronger argument why one should
disagree. Twelve years and 364 days from now, the European Union
states will be able to check today's flight plans. Here's what
bothers me.

<ul>

  <li> I am to assume that the retaining of data  will be in good
  trust, aimed at preventing terrorist attacks. </li>

  <li> I am to assume that the retaining of data  will not be aimed at good
  citizens to e.g. see if they travelled to their secret lover or to get
  some cheaper Wodka. </li>

  <li> I am to assume the retaining of data will not be aimed at
  checking whether I might've flown to some medical facility in say
  Spain, which might 
  indicate that I have a higher health risk of something or the other,
  which would mean that my health insurance policy might need
  reviewing. Or in the same vein, European governments will not check
  whether I've flown to some political meeting of some movement which
  is currently considered harmless, but which is frowned upon ten
  years from now. </li>
  
  <li> I am to assume that the retaing of data will not be aimed at collecting
  commercially valuable data that can be sold to airlines for a few
  quick euro's. </li>

  <li> I am to assume that during this whole period, my data will be
  rigorously protected and that no breach of privacy, leading to
  e.g. identity theft, will ever be possible. Meaning that:

  <ul>

    <li> The EU will make sure that only properly trained and
    supervised personnel will manage such data. The people around the
    data will never ever be morons who
    leave e.g. back up tapes in their car. Furthermore they will never
    ever be susceptible to
    bribery, nor will they ever be otherwise criminally inclined which
    might also lead to 
    the sell out of my data; </li>

    <li> The EU will make sure that the technological level of
    security is always higher than the one of potential attackers. The
    EU can guarantee that no technology will be developed between
    today and 13 years from now that could crack the security systems
    protecting my data. </li>

    </ul>

</ul>

<p/> Sorry, that's just asking too much. This regulation <b>forces</b>
me to put trust into the European governments not just in the present
time, but also in the future. Why should I concede that I will trust
the government of any (European) state thirteen years from now?

<p/> How can any organisation demand today that I should trust in them
in the future?

<p/> Also I wonder whether anyone has actually verified that storing
passenger data prevents hate speech and terrorist attacks. I strongly
suspect that the decisions are made by <a
href="http://www.kubat.nl/pages/blogaria/46#46">the people who have
the time, not the people who have the talent</a>. And of course by
politicians who act on a knee-jerk reflex: "Let's put
some kind of measure in place, it'll make the public will feel safer."
Does this mean that the decision makers think that no-one will
bother to check whether the measure actually makes sense? Decision
makers wake up! We're not a flock of idiots, stop treating us as such!

<p/> Incidentally, did anyone ever bother to go over the numbers? The
Dutch airport Schiphol (the largest one in the Netherlands) currently
ferries some 43 million passengers per year. So only for Schiphol
we'd have 43 million records a year to check. The
verification systems would of course be state of the art and highly
accurate - but however accurate a system is, it always yields a given
percentage of false positives ('hits' that initially ring a bell, need
to be further investigated to determine whether they indicate a
terrorist action, and -fortunately- in the end are found harmless). 

<p/> What percentage of false positives would such systems yield?
Ten percent? Five percent? Let's assume that the verification systems
would be so highly accurate as to yield only one percent false
positives. For Schiphol Airport only that would mean 1178 false
positives a day!

<p/> What will we do to battle such ridiculously high numbers?  We
might expand the police force to cope with such numbers. How
many extra officers would we need to check 1178 records each day?
What would such an officer do, run back ground checks on the
passenger? That way we could easily need 500+ extra personnel just
to check Schiphol. Would placing an extra 50 trained guards in and around
Schiphol be just as effective - if not more?

<p/> I'm sorry. The whole idea just doesn't make sense to me. Please
convince me otherwise!

 
</description>
   </item>
   <item>
    <title>BloggEd</title>
    <link>http://www.kubat.nl/pages/blogaria/50#50</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This cannot go unnoticed. Good buddy &amp; colleague Eddie
N. (featured here a number of times!)  has finally started jotting
down stories that show how weird he actually is ;-)

<p/>
Mostly for Dutch speakers and <b>really</b> worth the read: <a
href="http://eddie.niese.net" target="_blank">eddie.niese.net</a>.
 
</description>
   </item>
   <item>
    <title>Wilders and Marktplaats.nl</title>
    <link>http://www.kubat.nl/pages/blogaria/49#49</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Political cartoons <b>can</b> be funny, and they don't even have to be drawn
by professionals. If the conditions are right, humor will spring up
quite naturally - even better, there's nothing you could do about it
even if you wanted. Thus also illustrates the following cartoon.

<p/>
For Dutch oriented people it's pretty obvious. For non-Dutch oriented
folks, explaining it would totally kill it. So you either get it or not,
and you either like it or not. Here's to all of you opportunistic
populists who call themselves politicians. There are people who can
pretty much summarize your character in a few sentences, so beware.

<p/>
(This was seen in Amigoe, one of the main newspapers of Cura&ccedil;ao /
Netherlands Antilles. Shameless rip from <a
href="http://www.geenstijl.nl/mt/archieven/1069951.html"
target="_blank">Geenstijl.nl</a>.) 

<p/>

<center>
 <a href="http://www.kubat.nl/bld/amigoemarktplaats.jpg" target="_blank">
  <img src="http://www.kubat.nl/bld/amigoemarktplaats.jpg"
   width="480" height="331" border="0"/>
 </a>
</center>
   
</description>
   </item>
   <item>
    <title>The goldplated Mac</title>
    <link>http://www.kubat.nl/pages/blogaria/48#48</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 It seems that goldplating things is becoming quite an industry these
days. I remember my parents' generation, where casting baby shoes in
bronze was considered a cute souvenir - there's progress for ya,
nowadays you can get anything shiny and goldplated, a sure way to
catch everyone's eye.

<p/>
Recently I saw these two pictures of a goldplated Mac. Is that ugly or
what?

<p/>

<center>
 <img src="http://www.kubat.nl/bld/goldmac1.jpg" width="250" height="187"/>
 <img src="http://www.kubat.nl/bld/goldmac2.jpg" width="250" height="187"/>
</center>
 
  
</description>
   </item>
   <item>
    <title>More morons</title>
    <link>http://www.kubat.nl/pages/blogaria/47#47</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <h1>Let's have more morons</h1>

Recently I watched the movie <i>Idiocracy</i>, a comedy around the
hypothesis that the number of human offspring is inversely related to IQ -
so that eventually, the world's average person will become more and
more "stupid". The movie is a cute comedy, though around a theme
that's too scary to think about.

<p/>
The scary thing is, that I'm seeing things that already point to this
direction. Here's a few things off the top of my head.

<ul>

 <li> Students of the Dutch teacher's academy (PABO) come from average
 or above-average high schools. More than half of them could not solve
 the following question: <br/>

 <i>What is 20 divided by <sup>1</sup>/<sub>5</sub>?</i>

 <br/>
 They stated that in high school they were allowed to do use a
 calculator, so they weren't trained for this. Their spelling skills
 were below standards as well.
 
 </li>

 <li> The younger system administrators that I encounter in my daily
 routines are only used to "drag 'n' drop" administration. If a system
 doesn't have a GUI, they have a hard time understanding it and
 administering it. Tiny scripts that make a system self-administer
 itself are considered "applications", require "coding" and
 "developers" - while in my opinion, writing and maintaining such
 utilities is the core responsibility of administrators.</li> 

 <li> When planning a large project, I too often hear: "We'll need
 more people in the team for this". This so blandly disregards the
 Mythical Man Month. Why doesn't anyone come up with: "We'll need
 smarter people in the team for this"? </li>

 <li> My kids go to a primary school where the development of their personal
 self is stimulated. Actually I'm glad that this is the case, I can
 see them being able to cooperate with others, solve problems, create
 good looking Powerpoint presentations. They are well versed in
 history and tell great stories about ancient peoples and
 generals. But the school should also teach them two basic subjects:
 language (reading, writing, spelling) and calculus (fractions,
 percentages, negative numbers). These two subjects that I think are
 truly "primary" are tought sub-standard.

</ul>

So how are we going to turn this around? Or on an even more basic
level, when is someone going to stand up and say, "this has to be
turned around"?
 

  
</description>
   </item>
   <item>
    <title>Dilbert nails it again</title>
    <link>http://www.kubat.nl/pages/blogaria/46#46</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This was sent to me by good buddy Eddie N. It nails it -again-. Should
I laugh or cry?

<center>
 <img src="http://www.kubat.nl/bld/dilbert-20071026.gif"/>
</center>
 
</description>
   </item>
   <item>
    <title>Rough yet funny</title>
    <link>http://www.kubat.nl/pages/blogaria/45#45</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td width="200" valign="top">
   <img src="http://www.kubat.nl/bld/sui.gif" width="200"
    height="200"/>
  </td>
  <td valign="top">
   This was sent to me by my good collegue Emiel v.R. It's rough, but
   in a strange way really funny. Reminds me of my old nerdish days
   (hey, since when are they over anyway?)
  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Another silly Trojan mail</title>
    <link>http://www.kubat.nl/pages/blogaria/44#44</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Received today:

<p/>
<center>
 <img src="http://www.kubat.nl/bld/postcardexe.png"/>
</center>
<p/>

And guess what, you move the mouse over the hyperlink, and it shows..

<ul>

 <li> The site is in fact not <i>cards.123greetings.com</i>, but
 <i>mail.sharknet.ch</i>. Would that be some Chinese site? </li>

 <li> The hyperlink is to <i>postcard.jpg.exe</i>. Hmmm.. If I'm not
 mistaken, that's a filename that designates executables on MS-DOS
 systems (and derivatives). You know, the type of systems that use
 file names to determine what can be 'executed' and what not
 (ugggh). </li> 

 <p/> [Incidentally some bearded guys in the 70's or 80's found a better way
 for handling file properties (read/write/execute permissions,
 separately for the owner, group and world - the guys were the ones to
 invent Unix and lay the foundation for e.g. Linux, *BSD, and MacOSX).
 But MS-DOS got  
 invented 20 years later and the guys that worked on DOS, suffered from
 NIHS (Not Invented Here Syndrome). So they went ahead came up with a
 crappy solution - albeit a novel one.] </li>

</ul>

Incidentally, the e-mail continues to present more hyperlinks, incase
you miss the first one:

<p/>
<center>
 <img src="http://www.kubat.nl/bld/postcardmore.png"/>
</center>
<p/>

Guess what, the links lead to the same .exe, on the same Chinese
server.

<p/> Sad thing is, I'm pretty sure that some folks will click on it
and run the .exe. When is someone going to stand up and say, "Hey, we
require safety belts in cars in order to protect the general
public. Let's also require that OS builders stop producing crap."
 
</description>
   </item>
   <item>
    <title>So ugly it is beautiful</title>
    <link>http://www.kubat.nl/pages/blogaria/43#43</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
<tr>
 <td valign="top" width="508">
  <img src="http://www.kubat.nl/bld/Ripley.jpg"/>
 </td>
 <td valign="top">
  Sometimes things are so darn ugly that in the end one ends up
  getting used to them, and maybe even finding them beautiful.

  <p/>
  I recently tamed a new WoW pet, a real ugly and scarey
  one. It reminds me of an alien, and if I knew for sure that it's
  female, I would've called it Sigourney. But alas, as I'm not sure,
  it's just called Ripley.

  <p/>
  It's got a real tough skin, which is good (10.000+ armor)... so it
  suits its purpose perfectly. Now that I've been walking around with
  it for a week or two, I am even beginning to like it. 
 </td>
</tr>
</table>
 
</description>
   </item>
   <item>
    <title>Here is a nickel kid</title>
    <link>http://www.kubat.nl/pages/blogaria/42#42</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 They used to have some good Holy Wars in the past. Nowadays we have
only skirmishes - that is, apart from Operating System Holy
Wars. Still always good fun.

<p/>
<center>
 <img src="http://www.kubat.nl/bld/dilbert-unix-512px.png"/>
</center>
<p/>

"Hey that Linux laptop looks way cool.. think it would be something
for me?" <br/> 
"No. It's for experts." 
</description>
   </item>
   <item>
    <title>Spy Shredder</title>
    <link>http://www.kubat.nl/pages/blogaria/41#41</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <h1>Oh great! A spy shredder!</h1>

Recenty I got on a site that spontaneously started to verify how
healthy my sytem is. Golly! I didn't know they could do that for free
for me!

<p/>
<center>
 <img src="http://www.kubat.nl/img/spyshredder.png"/>
</center>
<p/>

Lucky me that I should stumble upon such a great site! They found that
my system isn't too healthy!

<p/>
<center>
 <img src="http://www.kubat.nl/img/spyshredder1.png"/>
</center>
<p/>

This is really my lucky day. And considering that I run Unix.. which
is obviously infected with .exe's and .dll's! I need to download their
free product ASAP so that I won't come to any harm in the future!

<p/>
(It's done neatly, gotta give 'em that. Looks like the real
thing. Still, you gotta be a sucker to fall for this kind of
crap. This week the news reported that cyber crime is making more
money than drugs, which is saying a lot.)
 
</description>
   </item>
   <item>
    <title>Web svn view 1.08</title>
    <link>http://www.kubat.nl/pages/blogaria/40#40</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 My <i>Easy SVN Viewer</i> web-svn-view is out with a new version:
1.08. This all new singing and dancing viewer displays differences
between versions better than the previous viewers.

<p/>
If you're interested:

<ul>
 <li> The package is hosted on <a href="http://public.e-tunity.com"
 target="_blank">http://public.e-tunity.com</a>, e-tunity's site with
 public downloads. You'll find both the <a
 href="http://public.e-tunity.com/web-svn-view/web-svn-view.html"
 target="_blank">docs</a> and <a
 href="http://public.e-tunity.com/web-svn-view/web-svn-view-latest.tar.gz">
 download archive</a> there. </li>  

 <li> Web-svn-view also has its Freshmeat page at <a
 href="http://freshmeat.net/projects/websvn/"
 target="_blank">http://freshmeat.net/projects/websvn/</a>. </li>

 <li> If you want to see it in action, browse e.g. the Crossroads SVN
 repository at <a href="http://crossroads.e-tunity.com/svnview.xr"
 target="_blank">http://crossroads.e-tunity.com/svnview.xr</a>. </li>

</ul>

As ever, this viewer is extremely simple to install - just one CGI
Perl script that queries a local SVN client and presents the output in a
nicely formatted way. 

<p/>
Thank you, Emiel van R. and other contributors for the changes that
led up to this version, which imho really improves the functionality!
  
</description>
   </item>
   <item>
    <title>Caught in THE Process</title>
    <link>http://www.kubat.nl/pages/blogaria/39#39</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Eddie N. is a colleague and good buddy who works as contractor
for the same company as I do, as general trouble shooter, programmer,
and what not. Today there was a request to update the "news" section
on a portal page, so that customers would be informed of some
important changes. Now, updating some HTML pages is in itself a very
trivial task. Placing these pages onto production webservers is also
very trivial, though it must be performed by another department
(ITO). And all this must be coordinated by the Change Management
Board, which is responsible for shipping deliverables back and forth
(from developers to ITO), for logging changes, for giving all
necessary aprovals, and for any or all other matters. You probably get
the idea.. all this leads to a Process which 
seriously hampers the Product we're all working on. Here are Eddies
remarks on this after a frustrating day. 

<p/>
<i>
L.S.,

<p/>
Since 18:00 CEST the pages are finally live. I'm sorry for
the delay. The delay was not due to technical reasons.
Everybody was on their toes to get this done quickly
however we got caught in the "change process" (again).

<p/>
The "change proces" is better known as "THE process"
to those who got caught but did manage to get out alive.
Don't get me wrong: processes are good. Processes prevent
us from falling into chaos and disorder. I do see the use
and need of processes.

<p/>
However "THE process" is not a regular business process.
"THE process" is an autonomous organism. It takes your work
(deliverables), chews on it and spits it right back at you.
In your face.

<p/>
Sometimes the deliverables will come out at the other end
of its digestive system (in this case you are considered
to be lucky). No matter what side your work leaves
"THE process" you know one thing for sure: your deliverables are
mutilated beyond recognition. 

<p/>
In some cases your binary files are transfered as text
files, effectively stripping every last bit of each byte.
Or linefeed characters are inserted into binary files.
Bottom-line: "THE process" has no respect for your work
whatsoever.

<p/>
Mutilation is not the only malfunction in "THE process".
Sometimes "THE process" manifests itself as a black-hole.
At first you feel lucky that your deliverables are
accepted so easily by "THE process". Unfortunately when
this happens the deliverables are not "accepted" but
"sucked into the black hole". Your deliverables (and
the change to which they belong) are gone forever. No
one knows where it is, nor where it went. "Was there a
change?". "I don't see a change". "Where is the change?".
"I don't think there was a change". "There is no change"
"No change".

<p/>
This is the right time to start calling people who are
close to "THE process". You always feel some comfort
when you get one on the phone. Later you'll realize that
these people are actually the henchmen of "THE process".
Sure they know that sometimes the change process
doesn't work too well. They will even admit that
"THE process" could be improved.  However: every
initiative to actually take on "THE process" is
clubbed to death like a pack of cute little seal-pups
looking for their Mommy.
That's why they are called henchmen. "Sure it's a bad
process, but it's OUR bad process and we will hang
on to it like there is no tomorrow".

<p/>
The henchmen try to tickle "THE process" in the hope that
the black hole will release the deliverable in one way
or the other. A curious pattern of redirecting you from
one henchman to the other is often involved here.

<p/>
You will always have to call at least five people before
"THE process" is tickled. The outcome of this largely
depends on who tickles "THE process" at what moment
and in what area. Tickling is really the only way to
get anything out of "THE process".

<p/>
To get approvals out of "THE process" is as difficult
as getting your deliverables out intact. "THE process"
is basically a large black box (or black hole). Nobody
really knows how this beast works. Why did the approval
come out? Who did what to get it? Can we do this again?
How do we get another approval? We did the same thing
as before but this time we did not get an approval.
How does this work?

<p/>
And this is exactly what happened today. It's really
absurd. On one side we have the company's business approval
from Brian G. Meanwhile on the other side we have the
techies at ITO lined up to actually perform the change.
We gave them the deliverables and the instructions
directly. Yes. We circumvented "THE process" for the
deliverables. The deliverables are handed to ITO directly
without allowing "THE process" to chew, eat and
mutilate them.

<p/>
When Brian gave the approval for the change the techies
at ITO were ready for the change at hand. They only
needed one thing: approval. So someone should
say "well if business approves this change it's
fine by me. I call the ITO guys and 5 minutes later
the change is installed succesfully".

<p/>
However doing so would circumvent "THE process".
The henchmen are alert on this. No approvals without
consulting "THE process". Believe me. I've called
several people multiple times. Harry K. called
several people multiple times. "THE process" must
have had a tickling like never before however it
held its ground. No approval came out of it. Sure
there was some output of "THE process". Stuff like:
"we disapprove this change because we never had to
approve this change in the first place". But that's
of no use to the ITO guys. We need more tickling.
I called. Harry called. I called again. Harry called
again. Tickle! Tickle it!! TICKLE!!!! TICKLE THE
BEAST!!

<p/>
No approval came out during the 3.5 to 4 hours of
tickling. Harry finally had to take matters into
his own hands and took full responsibility for any
consequences of performing this change without
approval from "THE process"... Harry is one
brave man. We will always remember him as the brave
manager who took responsibility. Who actually
took a stand against "THE process". Brave enough
to take matters into his own hands. Brave enough
to face the consequences. "We can DO this if we
bypass THE process" were his famous last words.

<p/>
Run people... RUN!! "THE process" is coming for
you next... He's coming for all of us... RUN!!
RUN!!! And don't look back. Keep running!!

<p/>
After this cynical rant I would like to wrap
things up with some science. According to the
first Theorem of Ludicrus this change process
is a complete waste of time. It's not flexible.
It can't cope with many kinds of changes. No one
really knows how this process works. Who is
supposed to do what to get the desired result?
The amount of effort that this process requires
to get anything done outweighs any possible
positive side-effects by far. Applying the first
theorem of Ludicrus to this process will proof
its utter futility.

<p/>
<b>"First theorem of Ludicrus:</b><br/>
Any process that requires more effort then
getting a woman to sleep with you will
render itself useless over time."

<p/>
This actually makes sense. Why waste so much
effort on this process while less effort gets
you way more satisfaction...

<p/>
Kill "THE process" before it kills you.

<p/>
Kind regards,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;Eddie.

</i>

 
</description>
   </item>
   <item>
    <title>Stupid Trojan attack</title>
    <link>http://www.kubat.nl/pages/blogaria/38#38</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Yesterday I received a pretty stupid e-mail with a too obvious Trojan attack:

<pre>
From: &lt;sandkb@aspentech.com&gt;
To: &lt;info@e-tunity.com&gt;
Subject: Re:
Date: Mon, 20 Aug 2007 15:45:41 -0500
MIME-Version: 1.0
Content-Type: text/plain;
        format=flowed;
        charset="windows-1252";
        reply-type=original
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.50.4927.1200
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4927.1200

Well you showed me yours, I guess I better show you mine, hehe.
check out my pics. http://220.131.38.189/
</pre>

The URL to 220.131.38.189 yields another too stupid page:

<pre>
HTTP/1.1 200 OK
Content-Type: text/html
Server: nginx/0.5.17
Date: Mon, 20 Aug 2007 23:04:11 GMT
X-Powered-By: PHP/5.2.1

If you do not see the Secure Login Window please install
our &lt;a href="/applet.exe"&gt;Secure Login Applet&lt;/a&gt;.
</pre>

Let's see who the sod is who distributes such crap (whois output):

<pre>
inetnum:      220.129.0.0 - 220.143.255.255
netname:      HINET-NET
country:      TW
descr:        CHTD, Chunghwa Telecom Co.,Ltd.
descr:        Data-Bldg.6F, No.21, Sec.21, Hsin-Yi Rd.
descr:        Taipei Taiwan 100
admin-c:      HN27-AP
tech-c:       HN28-AP
status:       ALLOCATED PORTABLE
changed:      hostmaster@twnic.net 20030611
mnt-by:       MAINT-TW-TWNIC
source:       APNIC
</pre>

Ah, a range. It'll be an ISP. Most likely one of their customers was
infected previously with this Trojan and now is propagating it.

<p/>
Now to fall for this, you would have to do two or maybe even three
stupid things:

<ul>

 <li>Click on the URL in the mail, which is specified by just an IP
 address;</li>
 
 <li>In the browser, truly "download an applet" which is an exe;</li>

 <li>In most cases the browser will warn you, and you need to click
 away the warning.

</ul>

Given the fact that this is just one of such obvious attacks that I've
seen lately, there must be some people who follow the above 
steps. Otherwise such attacks wouldn't propagate. In previous
situations I would try to contact the ISP of such an infected
system. Nowadays I don't even try, I've found ISP's nonresponding at best.

<p/>
Still it's pretty sad to see that anyone should fall for such
simplicity. Maybe these people are all newbies.. What's humanity coming to?

<center>
 <img src="http://www.kubat.nl/bld/compnewbies.gif"/>
</center>

  
</description>
   </item>
   <item>
    <title>Back in 1994</title>
    <link>http://www.kubat.nl/pages/blogaria/37#37</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Aah, the sweet old times. It all used to be so fun. Accidentally I
came across an
article on the First Dutch International Symposium on Linux, which I
co-organized back in 1994.

<p/>Me and a few colleagues (Frank Brokken and Piet Plomp) had decided
to organize this because Linux (at that point kernel 1.2 or similar)
was such great fun - especially when one was used to the IBM RT
series. The symposium was held in the Amsterdam "Rai", a 
huge congress center where we had a hall. The entrance fees were very
low; all we needed was to pay for the hall - and for one airline
ticket. Linus Torvalds came over, but had no money for the fare. There
was a panopticum of cool speakers and talks, of which I remember Matt
Welsh (porting to Linux), Remy Card (ext2) and of course Linus
himself, who opened and closed the two day symposium.

<p/>
A huge group of speakers and visitors went into the city that night to
have dinner and check out the sights. It was an amazing experience to
meet the core of the Linux movement that day.

<p/>
If you like to read some more, see <a
href="http://www.linuxjournal.com/article/1026"
target="_blank">http://www.linuxjournal.com/article/1026</a>,  
an article by Michael Johnson of the Linux Journal. He had a talk too
- about the way the journal affected Linux distribution.

<p/>
<center>
 <img src="http://www.kubat.nl/bld/MattWelsh.png"/> 
 <img src="http://www.kubat.nl/bld/LinusTorvalds.png"/> <br/>
 Matt Welsh and Linus Torvalds
</center>
 
</description>
   </item>
   <item>
    <title>A girly iPod</title>
    <link>http://www.kubat.nl/pages/blogaria/36#36</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td width="180" valign="top">
   <img src="http://www.kubat.nl/bld/ipod-nano.png"/>
  </td>
  <td valign="top">
   Some time ago while kidding around, I told my family that iPods
   were way cool and that I wouldn't mind walking around with one,
   even if it were bright pink.

   <p/>
   This weekend was my birthday, and guess what... I'm walking around
   with a bright pink "girly" iPod. And it's a great gadget, just what
   I'd wanted: easy to use, it does what it's supposed to do, no
   extra "features" that no-one would ever use, no moving parts (yes,
   I really wanted a diskless portable music player). Simply
   great. Color's a bit odd, but hey, it stands out.
  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Crossroads for RDP connections</title>
    <link>http://www.kubat.nl/pages/blogaria/35#35</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I received a very nice mail from Jase McC:

<pre>
I just wanted to say that Crossroads is a really nice application.
As a VMware guy, I'm always looking for a way to get more for less.
Connection Brokers, which are basically RDP/ICA load balancers
typically cost a fair amount of money.  I wrote an article on how
to use Crossroads as a Connection Broker for RDP connections.

Feel free to check it out my article at:
<a
href="http://www.jasemccarty.com/blog/2007/08/free-load-balancer-possible-connection.html"
target="_blank">http://www.jasemccarty.com/blog/2007/08/free-load-balancer-possible-connection.html</a>

Thanks for a great app.
</pre>

Much appreciated Jase! A great pleasure to get your mail and to read
your article!
 
</description>
   </item>
   <item>
    <title>Firewall art</title>
    <link>http://www.kubat.nl/pages/blogaria/34#34</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
  <td valign="top">
   Pioni-Sensei, aka Bart (son of my business partner Harry) created a
   way cool image of a firewall. I've heard that it will be used by a
   Thai magazine! Kudos, Pioni-Sensei! As far as I know, this is
   the first time that one of his pictures is used in publishing. Way to go!

   <p/>
   For more, check out his site at <a
   href="http://poni-sensei.deviantart.com/">DeviantArt</a>. 
  </td>
  <td width="300" valign="top">
   <img src="http://www.kubat.nl/bld/firewall_by_pioni_sensei.jpg"/>
  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>jpeginfo</title>
    <link>http://www.kubat.nl/pages/blogaria/33#33</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I frequently batch-convert jpeg images to smaller size, e.g. to use on
a web page. I've been Googling for a small and fast command line tool
to tell me per image what the current size is, and haven't been able
to find one! How odd.

<p/> So anyway, I decided to cook one myself, after I got fed up
searching. It's on <a href="http://www.kubat.nl/pages/jpeginfo">this
server</a> too.

 
</description>
   </item>
   <item>
    <title>Good People</title>
    <link>http://www.kubat.nl/pages/blogaria/32#32</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table width="100%">
 <tr>
 <td width="300" valign="top">
  <img src="http://www.kubat.nl/bld/highlands.jpg"/>
 </td>
 <td>
  Just returned from a week's holiday in Scotland. I know I know - had
  loads of holiday time this year, lucky git.

  <p/>
  Anyway, while in Scotland, me and the family met up with Internet
  buddies that we've known for a few months in the virtual world. It's
  the first  
  time that I've met virtual friends "irl" and I was quite nervous about
  it. The mental image of someone is often radically different from the
  real thing!

  <p/>
  I shouldn't have worried. Our virtual friends appeared to be 
  simply great people, who took us in, showed us around, lend us
  waterbottles, maps and other hiking accessories, and were
  just fantastic.

  <p/>
  So there are still Good People around. And they live in
  Scotland. Cheers, Pagann, Skiffle and Xack!
 </td>
 </tr>
</table> 
</description>
   </item>
   <item>
    <title>The Real Crossroads</title>
    <link>http://www.kubat.nl/pages/blogaria/31#31</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Sent to me by my buddy and former boss-colleague Frank Brokken. The
"real" Crossroads is at the Kerkstraat ("Church street") in
Groningen. They don't serve <a
href="http://crossroads.e-tunity.com">software balancers</a>, but
sandwiches, coffee and the like...

<p/>
<img src="http://www.kubat.nl/bld/xroads2.jpg"/>

<p/>
<img src="http://www.kubat.nl/bld/xroads4.jpg"/>
 
</description>
   </item>
   <item>
    <title>BBC Documentaries in the Netherlands</title>
    <link>http://www.kubat.nl/pages/blogaria/30#30</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I just got back from a beatiful two weeks' holiday in Spain. The
weather was just gorgeous, the sea was great, the company was
fantastic, the food and drink marvellous.

<p/>
Back in the Netherlands, the weather's all rainy and it's way too cold
for summer. And to top it off, one of the first news bits to reach me
is that one of the Dutch TV channels has sensored BBC documentaries to
suit their purposes. Richard Attenborough's beautiful nature
documentaries were stripped from references to evolutionary
effects. The TV channel company is -of course- EO, the Evangelists'
channel. (If you're interested: Dutch texts are available on <a 
href="http://evolutie.blog.com/"
target="_blank">http://evolutie.blog.com/</a>).  

<p/>
Aaaaarghh! I'm seriously contemplating moving to a different
country. And no, not the US of A - it looks like here in the
Netherlands we're experiencing some of the worst influences from
across the Atlantic. 
</description>
   </item>
   <item>
    <title>No problems with Crossroads so far</title>
    <link>http://www.kubat.nl/pages/blogaria/29#29</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Some time ago I mailed with Joern F., concerning a support request for
Crossroads (see the <a
href="http://www.kubat.nl/pages/blogaria/17">original
request</a>). Today I received a very nice mail from Joern:

<pre>
As promised some weeks ago, here one more report of our experiences
with your software. The conlusion is: It works great! We still use
version 1.44 and did not notice any problems since our last contact.

Thanks for your cool software!
</pre>

Always <i>very</i> nice to hear. Joern is using Crossroads as a front
end for 5 MySQL database servers. Here is the run report after a few
weeks of activity. 

<pre>
FYI - our status:

lxcross2:/etc/init.d # crossroads status
Service      : mysql, 146 live connections, last backend 0
  Backend  0 : ffm241 is available, 37 live connections
    Stats    : 26 failures out of 101234 connections
               usage 14762h12m10.09s, 726.74Gb
  Backend  1 : Ffm180 is available, 37 live connections
    Stats    : 8 failures out of 104824 connections
               usage 14940h42m53.84s, 718.88Gb
  Backend  2 : Ffmm229 is DOWN, 0 live connections
    Stats    : 1 failures out of 80527 connections
               usage 11748h2m23.93s, 554.81Gb
  Backend  3 : Ffm191 is available, 36 live connections
    Stats    : 0 failures out of 102600 connections
               usage 14969h36m25.69s, 722.84Gb
  Backend  4 : Ffm240 is available, 36 live connections
    Stats    : 33 failures out of 100306 connections
               usage 14419h11m46.20s, 713.77Gb
</pre>

Glad that it works, Joern!
 
</description>
   </item>
   <item>
    <title>Politically correct ad nauseam</title>
    <link>http://www.kubat.nl/pages/blogaria/28#28</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Lately I've been encountering a very curious perversion of grammar
use. It mainly occurs in 'serious' articles, and it has to be inspired
by the necessity to make such articles politically correct beyond any
doubt.

<p/>
Let me illustrate.

<p/>
<i>"Thus, if an individual does so-and-so, she has nothing to worry
about."</i> 

<p/>
Mind you, this is not about specifically men or women - it's about
people in general. 
Since when is "an individual" a feminine idiom for "human"? A few
years ago we could all enjoy the rise of the "they" form, as in 
<i>"Thus, if an individual does so-and-so, they have nothing to
worry about."</i> Personally, I find this almost as unnatural as the
"she" form. There's a weird singular/plural
transition here that doesn't belong.

<p/>
It looks as nowadays everyone needs to outdo that form to be even more
acceptable. 
Is the need for political correctness so compelling that we need to
circumvent grammar rules and invent gender switches just to be able to say,
"hey, my article is written in such a way that you need to take it
seriously"? Political correctness <i>ad nauseam</i> - or translated,
that makes you puke.

<p/> Why can't all the correctness-junkies out there just come to
terms with grammar? "Man" is a masculine gender word, even when used
in "mankind", or in a phrase like "Man has existed for thousands of
years". Yes yes yes - so have women. I know. Get a grip and move
on.

<p/>
Want to know something really shocking? The German word for girl,
"M&auml;dchen", is neither masculine nor feminine - it's neutral.
My prediction: In a few years such sentences will use the neutral "it", as in
<i>"thus, if an individual does so-and-so, it has nothing to worry
about."</i> Next,  all neutered cats will go ape and demand a
different phrasing.

 
</description>
   </item>
   <item>
    <title>Waka Waka Poem</title>
    <link>http://www.kubat.nl/pages/blogaria/27#27</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 The Waka Waka Poem is very old indeed. I remember seeing it back in
the eighties where ancient newsgroups like alt.humor would feature it
at least once a week. I haven't seen it for a few years now - so just
to make sure that this classic doesn't slide into oblivion, here it is
again. One of my all time favorites.

<pre>
<> !*''#               Waka waka bang splat tick tick hash,
^"`$$-                 Caret quote back-tick dollar dollar dash,
!*=@$_                 Bang splat equal at dollar under-score,
%*<> ~#4               Percent splat waka waka tilde number four,
&[]../                 Ampersand bracket bracket dot dot slash,
|{,,SYSTEM HALTED      Vertical-bar curly-bracket comma comma CRASH.
</pre>
 
</description>
   </item>
   <item>
    <title>Voyage of the rubber ducks</title>
    <link>http://www.kubat.nl/pages/blogaria/26#26</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Sometimes one will find an article that fires the imagination in an
unexpected way. Seen today on <a
href="http://www.dailymail.co.uk/pages/live/articles/news/news.html?in_article_id=464768&in_page_id=1770">The
Daily Mail</a>:

<p/>
"<i><b>Thousands of rubber ducks to land on British shores after 15
year journey</b>

<p/>
They were toys destined only to bob up and down in nothing bigger than
a child's bath - but so far they have floated halfway around the
world.
The armada of 29,000 plastic yellow ducks, blue turtles and green
frogs broke free from a cargo ship 15 years ago.
Since then they have travelled 17,000 miles, floating over the site
where the Titanic sank, landing in Hawaii and even spending years
frozen in an Arctic ice pack.
And now they are heading straight for Britain. At some point this
summer they are expected to be spotted on beaches in South-West
England."</i>

<p/>
<center>
<img src="http://www.kubat.nl/bld/rubberducks.jpg"/>
</center>
<p/>

The story also mentions one researcher Curtis Ebbesmeyer, who has
devoted loads of time to this subject. Oh one can only wish for such a
job. How cool would that be, to be able to say at a party, "Yeah,
well, I study the trek of rubber ducks.."
 
</description>
   </item>
   <item>
    <title>The On Off Switch</title>
    <link>http://www.kubat.nl/pages/blogaria/25#25</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
 <tr>
  <td valign="top" width="150">
   <img src="http://www.kubat.nl/bld/Switch.jpg"/>
  </td>

  <td>
   Today we had a blackout at the e-tunity.com server. It appeared
   that the hosting provider had replaced some power component during
   the last night, so that the power had been off for a little.

   <p/>
   The server is a great looking rack unit, with loads of lights and
   tiptronic switches in the front panel. Works way cool,
   except.. when the power is off, you have to touch the on button to
   start the server.

   </p>
   Not a very smart design for a rack based system. Whatever happened
   to the oldfashioned switches that would just have two positions, on
   and off, and would go <b>clang</b> when you flipped them? The
   advantage was that once they were in the on position, they would
   stay that way!

   <p/>
   It seems to me that this is one of the situations where a modern
   design with bells 'n' whistles is a bit overdone. My primary
   interest in server's design is that I just want it to be resilient as
   hell. I want to be forced to go to that rack on as few occasions as
   possible. And I don't care how the front panel looks; I'm even
   pretty sure that the folks at the hosting company don't care either.

  </td>
 </tr>
</table> 
</description>
   </item>
   <item>
    <title>No free lunch</title>
    <link>http://www.kubat.nl/pages/blogaria/24#24</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
 <tr>
  <td valign="top" width="70">
   <img src="http://www.kubat.nl/bld/flying-roman.gif"/>
  </td>
  <td valign="top">
   In search of a motto for the next week, I think I'll go for

   <p/>
   <center><b>Timeo Danaos et dona ferentes</b></center>

   <p/>
   (Translation: There's nothing like a free lunch. Actually this is Vergil's
   version of the Aeneas, where an advisor to the king of Troy states: "I
   fear the Greeks, even though they're bringing gifts." He meant to
   say: "Let's leave that damn horse outside the city gate, or better yet: burn
   it right here at the beach... cuz there's gotta be a downside here,
   there's nothing like a free lunch." The king should've realized this too.)
  </td>
 </tr>
</table> 
</description>
   </item>
   <item>
    <title>Crossroads web interface</title>
    <link>http://www.kubat.nl/pages/blogaria/23#23</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 It took me a while, but finally there's a web interface to
Crossroads. It's in the package as of version 1.46. The web interface
can report on the status of back ends, and you can toggle the status -
e.g., from <i>available</i> to <i>down</i> to take a back end offline.

<p/>
Here's a screen dump.

<p/>

<center>
 <img src="http://www.kubat.nl/bld/CrossroadsStatusOverview.png"/>
</center> 
</description>
   </item>
   <item>
    <title>Blinkenlights</title>
    <link>http://www.kubat.nl/pages/blogaria/22#22</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 An oldie goldie. Instructions: Print out in a large font, and
stick it onto the front panel of all running servers.

<center>
<pre>
-------------------------------------------------------------
  ACHTUNG! Alles touristen und non-technischen peepers!

  Das machine control is nicht fur gerfinger-poken und
  mittengrabben. Oderwise is easy schnappen der springenwerk,
  blowen fuse, und poppencorken mit spitzensparken.
  Der machine is diggen by experten only. Is nicht fur
  geverken by das dummkopfen. Das rubbernecken sightseenen
  keepen das cotten picken hands in das pockets,
  so relaxen und watchen das blinkenlights.
--------------------------------------------------------------
</pre>
</center>
 
</description>
   </item>
   <item>
    <title>There is no silver bullet</title>
    <link>http://www.kubat.nl/pages/blogaria/21#21</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I've spent a few years in software development, and I've very often
encountered folks who are frantically looking for the Solution to All
Problems, Once And For All. Or they're on the lookout for the next
software develpment methodology, that will Solve All Problems, Once
And For All. Or they're waiting for the next whatever thing to Solve
All Problems (you get the idea by now). In short, they want the Silver
Bullet. 

<p/>
Recently Jos Visser forwarded me an article by Daniel M. Berry, titled
<i>The Inevitable Pain of Software Development: Why There Is No Silver
Bullet</i>. The article has a nice theoretical background on why having a
silver bullet isn't possible. And from personal experience, this all
sounds <i>soooo true</i>. Plus, it's very interesting reading, in a
nerdish sort of way.

<p/>
The article is <a
href="http://www.kubat.nl/bld/rissef.painpaper.pdf">rissef.painpaper.pdf</a>.
Happy reading!

<p/>
(Dan Berry's restriction is that the paper may be downloaded only as a
whole. His personal page is <a
href="http://se.uwaterloo.ca/~dberry/">http://se.uwaterloo.ca/~dberry/</a>.)

 
</description>
   </item>
   <item>
    <title>Motto of the week</title>
    <link>http://www.kubat.nl/pages/blogaria/20#20</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 As for my motto of the week for the upcoming management meetings: I've
decided upon the following.

<p/>
<center>
 <b>Ceterum censeo Carthaginem esse delendam.</b>
</center>
<p/>

(Or translated: Besides, I think we should use more Open Source
components in our application infrastructure.

<p/>
Historical note: Cato, one of the Roman senators, used to nag the
Senate with this sentence, stating that in his opinion, the city of
Carthage should be destroyed. After some years the senate sent an army
and destroyed the city, and along with it, an entire culture. They
probably did so to get rid of the nagging and not because Carthage was
a threat. So - if I keep nagging as well, will I have my way too?)

 
</description>
   </item>
   <item>
    <title>Do not feed the troll</title>
    <link>http://www.kubat.nl/pages/blogaria/19#19</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Seen today on the Apache user's mailing list:

<p/>

<i>
"I noticed someone was using a CONNECT xxx.xxx.xxx.xxx http command
against Apache. I was wondering how to disable the CONNECT command
from executing on Apache. In a couple of entries I noticed a
connection from Seattle that might be a spammer so I want to disable
the CONNECT command from running successfully."
</i>

<p/>

Being a good Samaritan I replied with a few tips. But later I couldn't
help wondering: is this a troll who's hoping for a response like,
"Yeah, we have that at www.oursite.org as well", just to get a new
address of an open proxy?

<table>
 <tr>
  <td valign="top">
   Or is this a valid question on a list of
   an Apache self-help group? Am I being paranoid? Do I have reason to
   be?
  </td>
  <td valign="top">
   <img src="http://www.kubat.nl/bld/Calvin-and-Hobbes.png"/>
  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Which programming language are you</title>
    <link>http://www.kubat.nl/pages/blogaria/18#18</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Sunday afternoon, it's rainy, and I've got too much time on my
hands. So I take the quiz "Which programming language are you?". And
the results...

<p/>
<center>
<a href="http://www.bbspot.com/News/2006/08/language_quiz.php">
 <img src="http://www.kubat.nl/bld/lisp.jpg" width="300" height="90" border="0"
  alt="You are Lisp.  Very few people like you (Probably because you use too many parenthesis (You better stop it (Reallly)))">
</a>
</center>

<p/>
Aargh!
<br/>
(Click (on the image (above)) if you want to try (the (same) test))
 
</description>
   </item>
   <item>
    <title>Crossroads support request</title>
    <link>http://www.kubat.nl/pages/blogaria/17#17</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I recenty received a support request for Crossroads from Joern
F. His company runs Crossroads to balance database requests to a farm
of MySQL servers. After describing the bug, he writes...

<pre>
But anyway - and this must be mentioned - crossroads is a rocksolid
piece software! Easy to handle, fast and tiny. Thank you for writing it!

It would be a great favour for us if you find the time to analyse this.
</pre>

How could I refuse? (Well actually I'd have bugfixed Crossroads
anyway. It works the other way 'round - Joern, thanks for
reporting this!) Still, it's very nice to read.
 
</description>
   </item>
   <item>
    <title>Bokito glasses</title>
    <link>http://www.kubat.nl/pages/blogaria/16#16</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 There has been a tragic incident in the Netherlands where an alpha
male gorilla jumped a fence in a zoo and attacked a lady. Fortunately
she survived, though she was badly hurt.

<p> Though in itself this is a sad incident, the fun soon started. The
analysis as to why the ape attacked, was: the lady was smiling at
Bokito (the ape), and not averting her eyes - so in fact she was
provoking him. The proper way to be in the company of Bokito is to
avert your eyes, and never to show your teeth..

<p> Upon which some smartpants came up with an idea: why not
distribute glasses to zoo visitors that make your eyes seem to look
the other way? The purpose would be that the apes don't feel
observed. This was actually featured in a newspaper, I shit thee not.

<!-- Here used to be: BokitoGlasses.jpg -->

<p/> There's just one answer that remains: where the heck do I get those
glasses? I really need those for my upcoming work meetings...

<p/> <b>Update:</b> I had a photo here of the glasses in action.
Apparently I shouldn't have published that... more info to follow...
In the mean time, if you want to see the photo, google it.
 
</description>
   </item>
   <item>
    <title>Apache mod_proxy balancer description</title>
    <link>http://www.kubat.nl/pages/blogaria/15#15</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I'm trying out Apache 2.2.4's <i>mod_proxy</i> for balancing
purposes. The guys at Apache rock!

<p>
The text in <a target="_blank"
href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html">http://httpd.apache.org/docs/2.2/mod/mod_proxy.html</a>
is however slightly off. If you want to enable cookie stickiness, then
you'll need something like the following:

<pre>
    # URI /app goes to the balancer, and it's sticky by cookie CellColor
    ProxyPass		/app balancer://purple/app \
			stickysession=CellColor

    # The balancer with two worker, each having a route color
    &lt;Proxy		balancer://purple>
        BalancerMember	http://localhost:9001 route=red
        BalancerMember	http://localhost:9002 route=blue
    &lt;/Proxy>
</pre>

Now for the sticky cookie. There are two things involved:
<ul>
  <li> The cookie is named <i>CellColor</i>,
  <li> The routes are <i>red</i> and <i>blue</i>.
</ul>

<p>
The workers at <i>http://localhost:9001</i> and <i>9002</i> will now
have to inject cookies named <i>CellColor</i>, having the value
<i>balancer.red</i> or <i>balancer.blue</i>. Don't ask why
<i>balancer</i> must occur in the cookie value, I wouldn't know. If
there must be a prefix before <i>red</i> or <i>blue</i>, then I
would've expected the balancer's URI, in my example <i>purple</i>. Or
I wouldn't have expected a prefix at all, it's pretty redundant IMHO.

<p>
Anyway, injecting the cookies is trivial:
<pre>
# Red balancer member at port 9001
Header add Set-Cookie CellColor=balancer.red
</pre>

<pre>
# Blue balancer member at port 9002
Header add Set-Cookie CellColor=balancer.blue
</pre>
 
</description>
   </item>
   <item>
    <title>A ticketnumber is not support</title>
    <link>http://www.kubat.nl/pages/blogaria/14#14</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 My collegue &amp; buddy Eddie is planning to start an awareness
campaign, using the following slogans:

<p>
<center>
 <b>TICKETNUMBER != SUPPORT</b><br>
 <b>SOURCECODE == SUPPORT</b><br>
</center>
<p>

The plan is to spread the word on banners, pens, stickers, buttons,
posters, t-shirts, mugs, ties.. and what not. Then there's to be a
t-shirt with

<p>
<center>
 <b>"I called tech support &amp; all I got is this lousy
 ticketnumber"</b>
</center>
<p>

Brilliant, or what? I'm all for. Let's do it Eddie!
 
</description>
   </item>
   <item>
    <title>403 Hammertime</title>
    <link>http://www.kubat.nl/pages/blogaria/13#13</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Here's a great page that I shamelessly ripped from <a
href="http://uncyclopedia.org/wiki/MC_Hammer">uncyclopedia</a>. It's
a webserver error page for code 403, Temporarily unavailable..

<p>
<hr>
<table>
 <tr>
  <td valign="top">
   <div style="color:blue;font:13pt/15pt verdana;margin-left:2em;margin-right:1em;margin-bottom:0px;margin-top:5px">
    <img src="http://www.kubat.nl/bld/Information.gif">
    HTTP Error 403: Can't touch this!
   </div>
  </td>
  <td valign="top">
   <img src="http://www.kubat.nl/bld/Mchammer.gif">
  </td>
 </tr>
</table>

<hr>
<p>

Cute, or what?
 
</description>
   </item>
   <item>
    <title>Playground Fun</title>
    <link>http://www.kubat.nl/pages/blogaria/12#12</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 This is a somewhat odd picture taken at a Belgian playground. It's
been circulating the 'net for some time now...
<p>

<img src="http://www.kubat.nl/bld/playgroundfun.jpg">
 
</description>
   </item>
   <item>
    <title>Ascii man</title>
    <link>http://www.kubat.nl/pages/blogaria/11#11</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
 <tr>
  <td valign="top"> <img src="http://www.kubat.nl/bld/ASCII-Man1.gif"> </td>
  <td valign="top">
   Remember the old days when ascii art was still an item? <p>
   
   This is a pretty old image. I remember seeing it about two years
   ago, and it had already slipped my mind. But only almost. Now I saw
   it again, and it caught my eye again, so I thought I'd give it a
   place where I could find it again.
  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Cannot find the damn server</title>
    <link>http://www.kubat.nl/pages/blogaria/10#10</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Here's an alternative to IE's builtin 404 page. I think it has great
potential.

<p>
<img src="http://www.kubat.nl/bld/404.png">
<p>

(This was sent to me by Fred D., a valued collegue. Thanks FD!)
 
</description>
   </item>
   <item>
    <title>The BFG200</title>
    <link>http://www.kubat.nl/pages/blogaria/9#9</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 <table>
 <tr>
  <td valign="top">
   Ah, a faint echo from the past. This is actually a gun in World of
   Warcraft, and it's got some fancy name. But most of all it reminds me
   of the world famous "BFG 2000" gun of Doom, which could just zap
   anything. So big that the player should actually tip over when holding
   it.

   <p/>

   (This is me, Klinky, and the pet white tiger in Steamvaults.)
  <td valign="top">
   <img src="http://www.kubat.nl/bld/bfg2000.jpg">
  </td>
 </tr>
</table>
 
</description>
   </item>
   <item>
    <title>Crossroads Top User</title>
    <link>http://www.kubat.nl/pages/blogaria/8#8</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 There's another top user of Crossroads on the block. I received this
nice mail the other day.

<pre>
Service      : wwwhttp, 10 live connections, last backend 2
 Backend  0 : www1 is available, 3 live connections
   Stats    : 0 failures out of 2747362 connections, 2747362 sessions,
              usage 0.00s, 1.30103b
 Backend  1 : www2 is available, 5 live connections
   Stats    : 0 failures out of 5486943 connections, 5486941 sessions,
              usage 0.00s, 87.5869b
 Backend  2 : www3 is available, 2 live connections
   Stats    : 0 failures out of 5488705 connections, 5488702 sessions,
              usage 0.02s, 19.74Kb

running realy great :)
(4 days ~ 14 mio sessions => 3,5 mio per day)
</pre>

Now <b>that</b> is the sort of news to make my day... 
</description>
   </item>
   <item>
    <title>Crossroads Usage</title>
    <link>http://www.kubat.nl/pages/blogaria/7#7</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I received a short mail message with a remark and a
question concerning Crossroads (which aren't relevant here) -- but
anyway, it also stated 
the load that Crossroads handles at a given site.

<p>
At that site, Crossroads serves more than 2.500.000 (two and a half
million!) requests per day at that site. Now if that were a flat day
usage, I'd arrive at 104.000 hits per our, or 2.083 hits per minute,
or 28 per second. It's safe to assume that the distribution over the
day is in fact not flat, so just guessing.. the peaks may well range
to 140 - 280 per second. Maybe even more. 

<p>
Best thing ever is that the Linux system that runs Crossroads is on
the average 95% idle. During busy hours that number is around 87%. (So
still basically that system has a lot of spare time.)

<p>Currently this site is Crossroads' top consumer, hitwise. Maybe I
should send them a bunch of flowers or something?

 
</description>
   </item>
   <item>
    <title>The guy with the dark motorhelmet</title>
    <link>http://www.kubat.nl/pages/blogaria/6#6</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Some time ago I was at the railway station, preparing to get on a
train somewhere. It was one of the first nice and sunny days of the
year, and as I was early, I sort of lingered around outside the
station entrance.

<p>
The peace was suddenly disturbed by the sound of very loud exhaust
pipes. I, as many others, turned to see where the sound came from --
it turned out to be an approaching motorcycle. The driver was a big
mean looking fellow: he wore a motorcycle helmet with dark visor,
which totally obsured his face, a leather suit, and one of those cut
off Jeans jackets where the sleeves were removed. On the back side of
the jacket was a faded logo that had become unreadable.

<p>
The guy drove up sidewalk near the station entrance and revved
his huge engine, which was a true Harley. An uncommon sight in the
Netherlands, and especially so with the pipes that were custom made to
produce the roar. I'm sure that he enjoyed the noise and the
disapproving looks of all bystanders.

<p>
One of those bystanders was a little kid, no more than 8 years old. In
total admiration, with his mouth slightly open, he gawked at the cycle
and its driver. Then, very slowly, the motorcycle driver turned off
his hellish machine, dismounted, and slowly took off the
helmet. Contrary to my mind's image he turned out to be sixty-ish,
with grey hair and a trimmed beard. The boy who so admiringly
observed, couldn't hold it anymore, shouted, "Grandpa!", and ran
to him to be caught in a big bearhug.

<p>
It dawned on me that my mind's image of a Hell's Angel preparing a
train robbery might've been off. I observed the scene for a bit,
turned away, and entered the 
station to buy my train ticket. Later, while waiting for my train, I
saw grandpa and his grandson one more time. I also overheard a snippet
of their conversation; grandpa saying that he had sooo looked forward
to going to the zoo again with his grandson, and he wondered whether
that old fat rhino would still be there. But even better than
overhearing this, was the look on their faces: the grandson, glowing
with happiness, admiration and anticipation, and the grandfather,
glowing even more.

<p>
That day was a good day.  
</description>
   </item>
   <item>
    <title>The Process and The Result</title>
    <link>http://www.kubat.nl/pages/blogaria/5#5</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Professional life in a corporate environment never ceases to amaze
me. Over the years I've however detected a sort of Grand Scheme to
which everyone seems to adher and which constantly seems to stalk me
around, however I try to escape from it.

<p>
The Grand Scheme is: <i>Never mind the result, as long as the process
is OK.</i>

<p>
How in name of <i>insert-favorite-deity</i> is it possible that we all
think this way, like the proverbial lemmings that follow the tail in
front of them, even when it leads to catastrophe? It's a true mystery
for me. A great example is support contracts. Big companies pay tons
of cash for support, and they even continue to pay when the support is
below standard. They don't even mind when the support doesn't deliver!


<p>
And what to think of a support contract that states that the maximum
reaction time is 4 hours? That means that the ones who are supposed to
be the experts must call within 4 hours and say, yeah, hey, we got your
message, and we issued you a ticket. A bleeding ticket isn't support!
Support should be about the result, not the process to get there!

<p>As for me, I can only think of one reason for this. The manager who
arranges the support contract does this so that they can tell their
boss, yeah, I got it all managed - so where's my christmas
bonus. Their motive for getting the support in place isn't about the
result at all. And of course the party that provides the support is
more than happy to get away with a 4 hours response time, who wouldn't.

<p>For me, there's just one lesson here: during every conference,
at every decision moment, ask all who are involved: how does this help
the product, or is it just window dressing for the process?
When I try this, people look at me in a pretty strange way.. 
</description>
   </item>
   <item>
    <title>Quotes attributed to Jos</title>
    <link>http://www.kubat.nl/pages/blogaria/4#4</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 I've had the privilege of working with <a href="http://www.josvisser.nl">Jos
Visser</a> for well over a year. In a corporate environment where
procedures are discussed before results, he made a few very noteworthy
remarks. They may be somewhat paraphrased, or not entirely his by
origin -- but noteworthy nonetheless. If you have more, let me know!
(And as soon as I can think of some more, I'll add them..)

<ul>

  <li> <i>Your ass is grass, and I'm the lawnmower.</i> Spoken during
  a teleconference where he got somewhat agitated.

  <li> <i>Forget about operational excellence. Lets strive for
  operational mediocrisy.</i> He wasn't always too fond of the IT
  Operations procedures.

  <li> <i>We're up the proverbial creek without a paddle to row.</i>
  Remarked during a large scale black out of our systems.

  <li> <i>I'd like to make a movie, called the Corporate Hooligan.</i>
  He liked to envision himself as a corporate Jackass actor, storming
  into lunch meetings, grabbing food, and stuffing it into his mouth,
  just to piss off people. (Well, it <i>was</i> funny at that time.)

  <li> <i>There <b>is</b> no silver bullet.</i> Often remarked during
  meetings when a totally new approach or application was presented
  that was sure to solve all our software-related problems.

  <li> <i>If you can't impress them with excellence, dazzle them with
  bullshit.</i> Often used against vendors who present their product
  and talk the newest and hippest techno talk (and fail to camouflage
  how shallow their product is, if you listen carefully).

</ul>
 
</description>
   </item>
   <item>
    <title>A really nice comment about Crossroads</title>
    <link>http://www.kubat.nl/pages/blogaria/3#3</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 Today I received a great e-mail from GS, one of the people who use
Crossroads on a regular basis. After he'd helped me 
find a fault in Crossroads and after I'd made a fix, he wrote back:

<p/>
<i>
Thanks for this quick fix (again)!

<p/>
By the way: just yesterday I talked with an colleague about crossroads
and your support and we both agreed that the speed and quality of
support from your side is extra-ordinary. We both couldn't come up
with something comparable, neither with opensource projects nor with
paid support for proprietary software (and believe me, this company
pays quite a lot for support to various other companies...). 

<p/>
This being said, I'll start testing 1.30 right away. :-)
</i>

<p/> Now is this rewarding or what? Thanks again GS, for the truly
nice comment.

 
</description>
   </item>
   <item>
    <title>Kubat in the air</title>
    <link>http://www.kubat.nl/pages/blogaria/2#2</link>
    <pubDate>Sun, 13 Nov 11 13:33:05 +0100</pubDate>
    <description>
 How odd can things get? It would appear that there's a <i>Kubat
marker</i> in the Dutch airspace, to
be more precise: in the Northern part of the Netherlands, near
Groningen Airport.

<p> Thanks, Frank Brokken (good friend and former collegue) for
letting me know.

<center>
 <img src="http://www.kubat.nl/bld/Kubat-Vliegkaart-Eelde.jpg"
  alt="Kubat in the air"/>  
</center>

(Incase you're dyslexic: the Kubat marker is in the 048 degrees
direction from EHGG, in the top right hand corner of the image. It's
right on the Dutch border; beyond Kubat starts Germany.) 
</description>
   </item>

 </channel>
</rss>
 
