<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>technical</title>
  <subtitle>Posts containing technical information.</subtitle>
  <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/tags/technical"/>
  <link rel="self" type="application/atom+xml" href="http://michael.gorven.za.net/taxonomy/term/3/atom/feed"/>
  <id>http://michael.gorven.za.net/taxonomy/term/3/atom/feed</id>
  <updated>2008-08-17T16:54:09+02:00</updated>
  <entry>
    <title>New Knab modules</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/12/20/new-knab-modules" />
    <id>http://michael.gorven.za.net/blog/2008/12/20/new-knab-modules</id>
    <published>2008-12-20T20:50:37+01:00</published>
    <updated>2008-12-29T14:44:05+01:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="knab" />
    <category term="perl" />
    <category term="technical" />
    <summary type="html"><![CDATA[<p>I've recently been doing a lot of hacking on <a href="http://knab.omnia.za.net/">Knab</a>, which is the software
behind the <a href="http://wiki.clug.org.za/wiki/CLUG_IRC_Channel">#clug</a> <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat_bot">IRC bot</a>, <a href="http://wiki.clug.org.za/wiki/Spinach">Spinach</a>. I've contributed a number of new
modules, most of which are running on Spinach and are available from the main
<a href="http://bazaar-vcs.org/">Bazaar</a> repository.</p>

<h1>Events</h1>

<p>This module is basically a calendar feature which can store and retrieve events
such as birthdays. It also handles recurring events (both with rules<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> or
multiple dates).</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; Something happens on 21 December 2008 at 15:00
&amp;lt;Knab&amp;gt; yessir
&amp;lt;cocooncrash&amp;gt; When is something?
&amp;lt;Knab&amp;gt; something is on Sunday the 21st of December 2008 at 15:00:00
&amp;lt;cocooncrash&amp;gt; Forget event something
&amp;lt;Knab&amp;gt; I've forgotten something
&nbsp;
&amp;lt;cocooncrash&amp;gt; My birthday happens on 22 March every year
&amp;lt;Knab&amp;gt; sure
&amp;lt;cocooncrash&amp;gt; How long until cocooncrash's birthday?
&amp;lt;Knab&amp;gt; your birthday is 13 weeks and 1 day away
&amp;lt;cocooncrash&amp;gt; How many days until my birthday?
&amp;lt;Knab&amp;gt; your birthday is 92 days away
&nbsp;
&amp;lt;cocooncrash&amp;gt; When is Easter in 2010?
&amp;lt;Knab&amp;gt; Sun 4 Apr
&amp;lt;cocooncrash&amp;gt; What's happening on Tuesday
&amp;lt;Knab&amp;gt; National Chocolate Covered Anything Day and Day of Reconciliation
&amp;lt;cocooncrash&amp;gt; Search events for Outsider 
&amp;lt;Knab&amp;gt; Found: Be Friendly To Outsider Day, Be Hard On Outsider Day, Outsider's birthday, Outsider's dad's birthday,  (showing 4 of 4 results)</pre></div></pre></p>

<h1>Twitter</h1>

<p>This module retrieves messages posted on <a href="http://twitter.com/">Twitter</a> and <a href="http://identi.ca/">identi.ca</a>.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; Last twitter update by iolproofreader
&amp;lt;Knab&amp;gt; &quot;The ANC in the Eastern Cape is making it clear: it's either you're with us or not.&quot;
&amp;lt;cocooncrash&amp;gt; twitter 1067135354
&amp;lt;Knab&amp;gt; iolproofreader: &quot;&quot;Friend chases after golfer shot&quot; &lt;a href=&quot;http://tinyurl.com/4dn2lx&quot;
&amp;lt;cocooncrash&amp;gt;&quot; title=&quot;http://tinyurl.com/4dn2lx&quot;
&amp;lt;cocooncrash&amp;gt;&quot;&gt;http://tinyurl.com/4dn2lx&quot;
&amp;lt;cocooncrash&amp;gt;&lt;/a&gt; &lt;a href=&quot;http://twitter.com/iolproofreader/status/1067135354&quot; title=&quot;http://twitter.com/iolproofreader/status/1067135354&quot;&gt;http://twitter.com/iolproofreader/status/1067135354&lt;/a&gt;
&amp;lt;Knab&amp;gt; iolproofreader: &quot;Police are planning on more patrols and more scrutiny for travellers crossing the border of Swaziland and Mozambique.&quot;</pre></div></pre></p>

<h1>URLLengthen</h1>

<p>This modules discovers the URL which a shortened URL redirects to.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; &lt;a href=&quot;http://is.gd/1D&quot; title=&quot;http://is.gd/1D&quot;&gt;http://is.gd/1D&lt;/a&gt;
&amp;lt;Knab&amp;gt; &lt;a href=&quot;http://google.com/&quot; title=&quot;http://google.com/&quot;&gt;http://google.com/&lt;/a&gt;</pre></div></pre></p>

<h1>URLShorten</h1>

<p>This module creates a short URL using <a href="http://is.gd/">is.gd</a>.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; shorten &lt;a href=&quot;http://google.com/&quot; title=&quot;http://google.com/&quot;&gt;http://google.com/&lt;/a&gt;
&amp;lt;Knab&amp;gt; &lt;a href=&quot;http://is.gd/1D&quot; title=&quot;http://is.gd/1D&quot;&gt;http://is.gd/1D&lt;/a&gt;</pre></div></pre></p>

<h1>HTTP</h1>

<p>This module retrieves an HTTP URL and returns the result of the request.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; get &lt;a href=&quot;http://google.com&quot; title=&quot;http://google.com&quot;&gt;http://google.com&lt;/a&gt;
&amp;lt;Knab&amp;gt; 200 OK &quot;Google&quot;
&amp;lt;cocooncrash&amp;gt; Is google.com up?
&amp;lt;Knab&amp;gt; Yes, it's up
&amp;lt;cocooncrash&amp;gt; Is Twitter down?
&amp;lt;Knab&amp;gt; No, it's just you</pre></div></pre></p>

<h1>GoogleDefine</h1>

<p>This module gets definitions using Google.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; gdefine spinach
&amp;lt;Knab&amp;gt; &quot;dark green leaves; eaten cooked or raw in salads  &quot;, &quot;The Spinach (Eulithis mellinata) is a moth of the family Geometridae.</pre></div></pre></p>

<h1>Subversion</h1>

<p>This module retrieves commit messages from a <a href="http://subversion.tigris.org/">Subversion</a> repository.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; last commit
&amp;lt;Knab&amp;gt; r721 by trb143 7 hours ago: &quot;Update UI a bit to display columns&quot;
&amp;lt;cocooncrash&amp;gt; commit 700 full
&amp;lt;Knab&amp;gt; r700 by mgorven on 2008/12/15 at 21:14:26 UTC: &quot;Set non-existing config entries if requested with a default value, and create ~/.openlp when saving config file. &quot; M /openlp-2/trunk/openlp/core/utils/linregistry.py, M /openlp-2/trunk/openlp/core/utils/confighelper.py</pre></div></pre></p>

<h1>SummonJabber</h1>

<p>This module summons people by sending them a message via <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber</a>.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; cocooncrash.summon.jabber is &lt;a href=&quot;mailto:cocooncrash@example.com&quot;&gt;cocooncrash@example.com&lt;/a&gt;
&amp;lt;Knab&amp;gt; gotcha
&amp;lt;cocooncrash&amp;gt; summon cocooncrash
&amp;lt;Knab&amp;gt; I've summoned cocooncrash via Jabber</pre></div></pre></p>

<h1>Feeds</h1>

<p>This module retrieves <a href="http://en.wikipedia.org/wiki/RSS">RSS</a> and <a href="http://en.wikipedia.org/wiki/Atom_(standard)">Atom</a> feeds.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">&amp;lt;cocooncrash&amp;gt; Add feed &lt;a href=&quot;http://www.news24.com/news24RSSFeed/0,,2,00.xml&quot; title=&quot;http://www.news24.com/news24RSSFeed/0,,2,00.xml&quot;&gt;http://www.news24.com/news24RSSFeed/0,,2,00.xml&lt;/a&gt; as News24
&amp;lt;Knab&amp;gt; okay
&amp;lt;cocooncrash&amp;gt; latest articles from news24
&amp;lt;Knab&amp;gt; 0: &quot;SA's first San party launches&quot;, 1: &quot;Pakistan mall collapse: 3 dead&quot;, 2: &quot;Iran warship to fight pirates&quot;, 3: &quot;Westwood storms into lead&quot;, 4: &quot;US Embassy given the boot&quot;, 5: &quot;Jennifer Aniston's chilli Xmas&quot;
&amp;lt;cocooncrash&amp;gt; article 0 from News24
&amp;lt;Knab&amp;gt; &quot;SA's first San party launches&quot; &lt;a href=&quot;http://www.news24.com/News24/South_Africa/Politics/0,,2-7-12_2444493,00.html&quot; title=&quot;http://www.news24.com/News24/South_Africa/Politics/0,,2-7-12_2444493,00.html&quot;&gt;http://www.news24.com/News24/South_Africa/Politics/0,,2-7-12_2444493,00....&lt;/a&gt; : The first San political party has been launched at Upington in the Northern Cape. 
&amp;lt;cocooncrash&amp;gt; article /Palin/ from news24
&amp;lt;Knab&amp;gt; &quot;Drama in Palin household&quot; &lt;a href=&quot;http://www.news24.com/News24/World/News/0,,2-10-1462_2444295,00.html&quot; title=&quot;http://www.news24.com/News24/World/News/0,,2-10-1462_2444295,00.html&quot;&gt;http://www.news24.com/News24/World/News/0,,2-10-1462_2444295,00.html&lt;/a&gt; : The mother of  an 18-year-old man who plans to marry Alaska Governor Sarah Palin's  pregnant daughter, Bristol, has been arrested on drug charges.
&amp;lt;cocooncrash&amp;gt; list feeds
&amp;lt;Knab&amp;gt; m&amp;amp;g, clug park, haiybo, TechCrunch, onion, News24
&amp;lt;cocooncrash&amp;gt; remove news24 feed
&amp;lt;Knab&amp;gt; okay</pre></div></pre></p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>This feature is provided by the <a href="http://search.cpan.org/~sbeck/Date-Manip-5.54/">Date::Manip</a> library.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>I've recently been doing a lot of hacking on <a href="http://knab.omnia.za.net/">Knab</a>, which is the software
behind the <a href="http://wiki.clug.org.za/wiki/CLUG_IRC_Channel">#clug</a> <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat_bot">IRC bot</a>, <a href="http://wiki.clug.org.za/wiki/Spinach">Spinach</a>. I've contributed a number of new
modules, most of which are running on Spinach and are available from the main
<a href="http://bazaar-vcs.org/">Bazaar</a> repository.</p>

<h1>Events</h1>

<p>This module is basically a calendar feature which can store and retrieve events
such as birthdays. It also handles recurring events (both with rules<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> or
multiple dates).</p>

<pre><code>&lt;cocooncrash&gt; Something happens on 21 December 2008 at 15:00
&lt;Knab&gt; yessir
&lt;cocooncrash&gt; When is something?
&lt;Knab&gt; something is on Sunday the 21st of December 2008 at 15:00:00
&lt;cocooncrash&gt; Forget event something
&lt;Knab&gt; I've forgotten something

&lt;cocooncrash&gt; My birthday happens on 22 March every year
&lt;Knab&gt; sure
&lt;cocooncrash&gt; How long until cocooncrash's birthday?
&lt;Knab&gt; your birthday is 13 weeks and 1 day away
&lt;cocooncrash&gt; How many days until my birthday?
&lt;Knab&gt; your birthday is 92 days away

&lt;cocooncrash&gt; When is Easter in 2010?
&lt;Knab&gt; Sun 4 Apr
&lt;cocooncrash&gt; What's happening on Tuesday
&lt;Knab&gt; National Chocolate Covered Anything Day and Day of Reconciliation
&lt;cocooncrash&gt; Search events for Outsider 
&lt;Knab&gt; Found: Be Friendly To Outsider Day, Be Hard On Outsider Day, Outsider's birthday, Outsider's dad's birthday,  (showing 4 of 4 results)
</code></pre>

<h1>Twitter</h1>

<p>This module retrieves messages posted on <a href="http://twitter.com/">Twitter</a> and <a href="http://identi.ca/">identi.ca</a>.</p>

<pre><code>&lt;cocooncrash&gt; Last twitter update by iolproofreader
&lt;Knab&gt; "The ANC in the Eastern Cape is making it clear: it's either you're with us or not."
&lt;cocooncrash&gt; twitter 1067135354
&lt;Knab&gt; iolproofreader: ""Friend chases after golfer shot" http://tinyurl.com/4dn2lx"
&lt;cocooncrash&gt; <a href="http://twitter.com/iolproofreader/status/1067135354" title="http://twitter.com/iolproofreader/status/1067135354">http://twitter.com/iolproofreader/status/1067135354</a>
&lt;Knab&gt; iolproofreader: "Police are planning on more patrols and more scrutiny for travellers crossing the border of Swaziland and Mozambique."
</code></pre>

<h1>URLLengthen</h1>

<p>This modules discovers the URL which a shortened URL redirects to.</p>

<pre><code>&lt;cocooncrash&gt; <a href="http://is.gd/1D" title="http://is.gd/1D">http://is.gd/1D</a>
&lt;Knab&gt; <a href="http://google.com/" title="http://google.com/">http://google.com/</a>
</code></pre>

<h1>URLShorten</h1>

<p>This module creates a short URL using <a href="http://is.gd/">is.gd</a>.</p>

<pre><code>&lt;cocooncrash&gt; shorten <a href="http://google.com/" title="http://google.com/">http://google.com/</a>
&lt;Knab&gt; <a href="http://is.gd/1D" title="http://is.gd/1D">http://is.gd/1D</a>
</code></pre>

<h1>HTTP</h1>

<p>This module retrieves an HTTP URL and returns the result of the request.</p>

<pre><code>&lt;cocooncrash&gt; get <a href="http://google.com" title="http://google.com">http://google.com</a>
&lt;Knab&gt; 200 OK "Google"
&lt;cocooncrash&gt; Is google.com up?
&lt;Knab&gt; Yes, it's up
&lt;cocooncrash&gt; Is Twitter down?
&lt;Knab&gt; No, it's just you
</code></pre>

<h1>GoogleDefine</h1>

<p>This module gets definitions using Google.</p>

<pre><code>&lt;cocooncrash&gt; gdefine spinach
&lt;Knab&gt; "dark green leaves; eaten cooked or raw in salads  ", "The Spinach (Eulithis mellinata) is a moth of the family Geometridae.
</code></pre>

<h1>Subversion</h1>

<p>This module retrieves commit messages from a <a href="http://subversion.tigris.org/">Subversion</a> repository.</p>

<pre><code>&lt;cocooncrash&gt; last commit
&lt;Knab&gt; r721 by trb143 7 hours ago: "Update UI a bit to display columns"
&lt;cocooncrash&gt; commit 700 full
&lt;Knab&gt; r700 by mgorven on 2008/12/15 at 21:14:26 UTC: "Set non-existing config entries if requested with a default value, and create ~/.openlp when saving config file. " M /openlp-2/trunk/openlp/core/utils/linregistry.py, M /openlp-2/trunk/openlp/core/utils/confighelper.py
</code></pre>

<h1>SummonJabber</h1>

<p>This module summons people by sending them a message via <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber</a>.</p>

<pre><code>&lt;cocooncrash&gt; cocooncrash.summon.jabber is <a href="mailto:cocooncrash@example.com">cocooncrash@example.com</a>
&lt;Knab&gt; gotcha
&lt;cocooncrash&gt; summon cocooncrash
&lt;Knab&gt; I've summoned cocooncrash via Jabber
</code></pre>

<h1>Feeds</h1>

<p>This module retrieves <a href="http://en.wikipedia.org/wiki/RSS">RSS</a> and <a href="http://en.wikipedia.org/wiki/Atom_(standard)">Atom</a> feeds.</p>

<pre><code>&lt;cocooncrash&gt; Add feed <a href="http://www.news24.com/news24RSSFeed/0,,2,00.xml" title="http://www.news24.com/news24RSSFeed/0,,2,00.xml">http://www.news24.com/news24RSSFeed/0,,2,00.xml</a> as News24
&lt;Knab&gt; okay
&lt;cocooncrash&gt; latest articles from news24
&lt;Knab&gt; 0: "SA's first San party launches", 1: "Pakistan mall collapse: 3 dead", 2: "Iran warship to fight pirates", 3: "Westwood storms into lead", 4: "US Embassy given the boot", 5: "Jennifer Aniston's chilli Xmas"
&lt;cocooncrash&gt; article 0 from News24
&lt;Knab&gt; "SA's first San party launches" <a href="http://www.news24.com/News24/South_Africa/Politics/0,,2-7-12_2444493,00.html" title="http://www.news24.com/News24/South_Africa/Politics/0,,2-7-12_2444493,00.html">http://www.news24.com/News24/South_Africa/Politics/0,,2-7-12_2444493,00....</a> : The first San political party has been launched at Upington in the Northern Cape. 
&lt;cocooncrash&gt; article /Palin/ from news24
&lt;Knab&gt; "Drama in Palin household" <a href="http://www.news24.com/News24/World/News/0,,2-10-1462_2444295,00.html" title="http://www.news24.com/News24/World/News/0,,2-10-1462_2444295,00.html">http://www.news24.com/News24/World/News/0,,2-10-1462_2444295,00.html</a> : The mother of  an 18-year-old man who plans to marry Alaska Governor Sarah Palin's  pregnant daughter, Bristol, has been arrested on drug charges.
&lt;cocooncrash&gt; list feeds
&lt;Knab&gt; m&amp;g, clug park, haiybo, TechCrunch, onion, News24
&lt;cocooncrash&gt; remove news24 feed
&lt;Knab&gt; okay
</code></pre>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>This feature is provided by the <a href="http://search.cpan.org/~sbeck/Date-Manip-5.54/">Date::Manip</a> library.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
  <entry>
    <title>Playing with Python and IRC</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/10/31/playing-python-irc" />
    <id>http://michael.gorven.za.net/blog/2008/10/31/playing-python-irc</id>
    <published>2008-10-31T23:58:40+01:00</published>
    <updated>2008-11-01T00:06:40+01:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="bots" />
    <category term="irc" />
    <category term="python" />
    <category term="sports" />
    <category term="technical" />
    <summary type="html"><![CDATA[<p>I wrote three <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"><abbr title="Internet Relay Chat">IRC</abbr></a> <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat_bot">bots</a> in <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> this last week (although one was a
rewrite). They probably aren't very useful to most people, but I'm going to share
them anyway in case someone finds them interesting.</p>

<p>The first one was prompted by <a href="http://changeover.za.net/">Adrian</a>, who is maintaining a <a href="http://pepper.omnia.za.net/spinach/spinach.php?fact=Outsider.countdown&amp;searchfact=plain&amp;verb=&amp;value=&amp;searchvalue=full">countdown</a> until his
wedding as a factoid in <a href="http://wiki.clug.org.za/wiki/Spinach">Spinach</a>. Since <a href="http://knab.omnia.za.net/">Knab</a> doesn't actually support countdowns,
it has to be updated manually. This clearly isn't the Right Way to do this, and so I
hacked together a <a href="/files/countdown-simple.py.txt">script</a> which connects to <abbr title="Internet Relay Chat">IRC</abbr> and teaches Spinach the updated factoid.
I run this as a daily <a href="http://en.wikipedia.org/wiki/Cron">cronjob</a> to keep the countdown up to date.</p>

<p>As is usually the case with Python, there was already a library for accessing <abbr title="Internet Relay Chat">IRC</abbr>,
namely <a href="http://python-irclib.sourceforge.net/">irclib</a>. It isn't documented very well, but has a couple example scripts
which are fairly easy to follow. It follows an event based model, so you write functions
which will be called when certain events occur (such as receiving a message).</p>

<p>The final of the <a href="http://en.wikipedia.org/wiki/Currie_Cup">Currie Cup</a> was held on Saturday (which my team (the <a href="http://en.wikipedia.org/wiki/Natal_Sharks">Sharks</a>) won),
and I followed the match online using <a href="http://www.supersport.co.za/">SuperSport's</a> live score site<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. I then thought
that it would be cool to have the score announced on <abbr title="Internet Relay Chat">IRC</abbr> when it changed, and since I was bored
I wrote a simple <a href="/files/rugbybot-simple.py.txt">bot</a> to do this. It worked well, but was very simple in that it
only supported one hardcoded channel and one hardcoded game.</p>

<p>Since I was also bored on Sunday I <a href="/files/rugbybot.py.txt">rewrote</a> this bot properly. I added a subscription
mechanism so that channels and users can subscribe and unsubscribe to games by sending the bot a command. It's
mostly working except for listing the available games (since there aren't any rugby games coming
up which means that I can't test it ;-) ). Games are specified by the ID used by SuperSport's site,
and finding the right ID is currently a manual process.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>I'm not really a sports fan — I just enjoy bragging when we do win ;-)&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>I wrote three <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"><abbr title="Internet Relay Chat">IRC</abbr></a> <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat_bot">bots</a> in <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> this last week (although one was a
rewrite). They probably aren't very useful to most people, but I'm going to share
them anyway in case someone finds them interesting.</p>

<p>The first one was prompted by <a href="http://changeover.za.net/">Adrian</a>, who is maintaining a <a href="http://pepper.omnia.za.net/spinach/spinach.php?fact=Outsider.countdown&amp;searchfact=plain&amp;verb=&amp;value=&amp;searchvalue=full">countdown</a> until his
wedding as a factoid in <a href="http://wiki.clug.org.za/wiki/Spinach">Spinach</a>. Since <a href="http://knab.omnia.za.net/">Knab</a> doesn't actually support countdowns,
it has to be updated manually. This clearly isn't the Right Way to do this, and so I
hacked together a <a href="/files/countdown-simple.py.txt">script</a> which connects to <abbr title="Internet Relay Chat">IRC</abbr> and teaches Spinach the updated factoid.
I run this as a daily <a href="http://en.wikipedia.org/wiki/Cron">cronjob</a> to keep the countdown up to date.</p>

<p>As is usually the case with Python, there was already a library for accessing <abbr title="Internet Relay Chat">IRC</abbr>,
namely <a href="http://python-irclib.sourceforge.net/">irclib</a>. It isn't documented very well, but has a couple example scripts
which are fairly easy to follow. It follows an event based model, so you write functions
which will be called when certain events occur (such as receiving a message).</p>

<p>The final of the <a href="http://en.wikipedia.org/wiki/Currie_Cup">Currie Cup</a> was held on Saturday (which my team (the <a href="http://en.wikipedia.org/wiki/Natal_Sharks">Sharks</a>) won),
and I followed the match online using <a href="http://www.supersport.co.za/">SuperSport's</a> live score site<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. I then thought
that it would be cool to have the score announced on <abbr title="Internet Relay Chat">IRC</abbr> when it changed, and since I was bored
I wrote a simple <a href="/files/rugbybot-simple.py.txt">bot</a> to do this. It worked well, but was very simple in that it
only supported one hardcoded channel and one hardcoded game.</p>

<p>Since I was also bored on Sunday I <a href="/files/rugbybot.py.txt">rewrote</a> this bot properly. I added a subscription
mechanism so that channels and users can subscribe and unsubscribe to games by sending the bot a command. It's
mostly working except for listing the available games (since there aren't any rugby games coming
up which means that I can't test it ;-) ). Games are specified by the ID used by SuperSport's site,
and finding the right ID is currently a manual process.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>I'm not really a sports fan — I just enjoy bragging when we do win ;-)&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
  <entry>
    <title>Sharing links from Konqueror, including to IRC</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/10/24/sharing-links-konqueror-including-irc" />
    <id>http://michael.gorven.za.net/blog/2008/10/24/sharing-links-konqueror-including-irc</id>
    <published>2008-10-24T17:09:12+02:00</published>
    <updated>2008-11-01T00:38:32+01:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="code" />
    <category term="irc" />
    <category term="kdialog" />
    <category term="konqueror" />
    <category term="linux" />
    <category term="social" />
    <category term="technical" />
    <category term="ubuntu" />
    <category term="weechat" />
    <summary type="html"><![CDATA[<p>I follow the main feeds of a couple social news sites (namely <a href="http://digg.com/">Digg</a>, <a href="http://www.reddit.com/">Reddit</a> and <a href="http://muti.co.za/">Muti</a>).
When I find an article which I like, I go back and vote it up on the site. However, when I come
across good articles via other sources, I don't submit them to these news sites (or try to find out
if they've already been submitted) simply because it's too much effort.</p>

<p>When I started aggregating my activity on these sites on my blog and on <a href="http://friendfeed.com/">FriendFeed</a>, I needed a
way to share pages that I didn't get to via one of these social news sites. I ended up setting up
<a href="http://delicious.com/">Delicious</a> because I found a <a href="http://www.kde-apps.org/content/show.php?content=18909">plugin</a> for <a href="http://en.wikipedia.org/wiki/Konqueror">Konqueror</a> which made it easy to bookmark pages.</p>

<p>I still wanted to solve the original problem though, and so started looking for an easy way to
submit links to these sites from Konqueror. Konqueror has a feature called <a href="http://developer.kde.org/documentation/tutorials/dot/servicemenus.html">service menus</a> which
allows you to add entries to the context menu of files. I then needed to work out how to submit
links to these services, which turned out to simply involve loading a <abbr title="Uniform Resource Locator">URL</abbr> with a query parameter
specifying the link you want to share.</p>

<p>I created entries for <a href="http://www.reddit.com/">Reddit</a>, <a href="http://digg.com/">Digg</a>, <a href="http://muti.co.za/">Muti</a>, <a href="http://delicious.com/">Delicious</a>, <a href="http://www.facebook.com/">Facebook</a> and <a href="http://www.google.com/bookmarks/">Google
Bookmarks</a>. These take you to the submission page of the service where you can fill in the
title<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. Digg and Reddit will show existing submissions if the link has already been submitted.</p>

<p>I often share links on <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"><abbr title="Internet Relay Chat">IRC</abbr></a>, and wondered if I could integrate that with my menu. It turns out
that <a href="http://weechat.flashtux.org/">WeeChat</a> has a control socket, and I could send messages by piping them to the socket. I
therefore wrote a script which prompted me for a headline or excerpt using <a href="http://techbase.kde.org/Development/Tutorials/Shell_Scripting_with_KDE_Dialogs">kdialog</a>, and then
sent the link to the specified channel. My menu now looks like this:</p>

<p><center><a href="/sites/michael.gorven.za.net/files/sharemenu.png" class="inline-image-link" title="View: sharemenu.png"><img src="http://michael.gorven.za.net/sites/michael.gorven.za.net/files/imagecache/medium/sharemenu.png" alt="sharemenu.png" title="sharemenu.png"  class="inline" /></a></center></p>

<p>If you want to set this up yourself, download <a href="/files/share.desktop">share.desktop</a> and put it in
<span class="geshifilter"><code class="geshifilter-text">~/.kde/share/apps/konqueror/servicemenus</code></span>. If you want the icons, download <a href="/files/shareicons.tar.gz">shareicons.tar.gz</a>,
extract them somewhere, and fix the paths in <span class="geshifilter"><code class="geshifilter-text">social.desktop</code></span><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>. To setup the <abbr title="Internet Relay Chat">IRC</abbr> feature
(assuming you're using WeeChat), download <a href="/files/postirc.sh">postirc.sh</a> and save it in <span class="geshifilter"><code class="geshifilter-text">~/bin/</code></span>. You will need to
change the commands in <span class="geshifilter"><code class="geshifilter-text">social.desktop</code></span> depending on the servers and channels you wish to use.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>One shortcoming is that the title of the page is not automatically filled in.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p>I couldn't work out how to use relative paths, or ~.&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>I follow the main feeds of a couple social news sites (namely <a href="http://digg.com/">Digg</a>, <a href="http://www.reddit.com/">Reddit</a> and <a href="http://muti.co.za/">Muti</a>).
When I find an article which I like, I go back and vote it up on the site. However, when I come
across good articles via other sources, I don't submit them to these news sites (or try to find out
if they've already been submitted) simply because it's too much effort.</p>

<p>When I started aggregating my activity on these sites on my blog and on <a href="http://friendfeed.com/">FriendFeed</a>, I needed a
way to share pages that I didn't get to via one of these social news sites. I ended up setting up
<a href="http://delicious.com/">Delicious</a> because I found a <a href="http://www.kde-apps.org/content/show.php?content=18909">plugin</a> for <a href="http://en.wikipedia.org/wiki/Konqueror">Konqueror</a> which made it easy to bookmark pages.</p>

<p>I still wanted to solve the original problem though, and so started looking for an easy way to
submit links to these sites from Konqueror. Konqueror has a feature called <a href="http://developer.kde.org/documentation/tutorials/dot/servicemenus.html">service menus</a> which
allows you to add entries to the context menu of files. I then needed to work out how to submit
links to these services, which turned out to simply involve loading a <abbr title="Uniform Resource Locator">URL</abbr> with a query parameter
specifying the link you want to share.</p>

<p>I created entries for <a href="http://www.reddit.com/">Reddit</a>, <a href="http://digg.com/">Digg</a>, <a href="http://muti.co.za/">Muti</a>, <a href="http://delicious.com/">Delicious</a>, <a href="http://www.facebook.com/">Facebook</a> and <a href="http://www.google.com/bookmarks/">Google
Bookmarks</a>. These take you to the submission page of the service where you can fill in the
title<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. Digg and Reddit will show existing submissions if the link has already been submitted.</p>

<p>I often share links on <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"><abbr title="Internet Relay Chat">IRC</abbr></a>, and wondered if I could integrate that with my menu. It turns out
that <a href="http://weechat.flashtux.org/">WeeChat</a> has a control socket, and I could send messages by piping them to the socket. I
therefore wrote a script which prompted me for a headline or excerpt using <a href="http://techbase.kde.org/Development/Tutorials/Shell_Scripting_with_KDE_Dialogs">kdialog</a>, and then
sent the link to the specified channel. My menu now looks like this:</p>

<p><center><a href="/sites/michael.gorven.za.net/files/sharemenu.png" class="inline-image-link" title="View: sharemenu.png"><img src="http://michael.gorven.za.net/sites/michael.gorven.za.net/files/imagecache/medium/sharemenu.png" alt="sharemenu.png" title="sharemenu.png"  class="inline" /></a></center></p>

<p>If you want to set this up yourself, download <a href="/files/share.desktop">share.desktop</a> and put it in
<code>~/.kde/share/apps/konqueror/servicemenus</code>. If you want the icons, download <a href="/files/shareicons.tar.gz">shareicons.tar.gz</a>,
extract them somewhere, and fix the paths in <code>social.desktop</code><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>. To setup the <abbr title="Internet Relay Chat">IRC</abbr> feature
(assuming you're using WeeChat), download <a href="/files/postirc.sh">postirc.sh</a> and save it in <code>~/bin/</code>. You will need to
change the commands in <code>social.desktop</code> depending on the servers and channels you wish to use.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>One shortcoming is that the title of the page is not automatically filled in.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p>I couldn't work out how to use relative paths, or ~.&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
  <entry>
    <title>Windows users finally get circular scrolling</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/10/01/windows-users-finally-get-circular-scrolling" />
    <id>http://michael.gorven.za.net/blog/2008/10/01/windows-users-finally-get-circular-scrolling</id>
    <published>2008-10-01T17:12:23+02:00</published>
    <updated>2008-10-01T17:12:23+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="chiraltouch" />
    <category term="linux" />
    <category term="synaptics" />
    <category term="technical" />
    <category term="touchpad" />
    <category term="windows" />
    <summary type="html"><![CDATA[<p>When I first started using Linux four years ago, one of the most useful
features I discovered was circular scrolling on <a href="http://en.wikipedia.org/wiki/Touchpad">touchpads</a>. (For those that
don't know, this allows you to scroll up and down by moving your finger in a
circle.) Traditional scrolling now feels very clumsy, and I find it awkward
when using a laptop which doesn't have this feature (such as those running
Windows). According to the <a href="http://web.telia.com/~u89404340/touchpad/files/changes.txt">changelog</a> for the <a href="http://en.wikipedia.org/wiki/X.Org_Server">XOrg</a>/<a href="http://en.wikipedia.org/wiki/XFree86">XFree86</a> Synaptics
<a href="http://web.telia.com/~u89404340/touchpad/">driver</a>, this feature was added in February 2004.</p>

<p>I happened to come across the <a href="http://lifehacker.com/5057317/synaptics-adds-mac+like-gestures-to-touchpads">news</a> today that <a href="http://en.wikipedia.org/wiki/Synaptics">Synaptics</a> have added a
feature called <em><a href="http://www.synaptics.com/technology/chiral.cfm">ChiralTouch Technology</a></em> to the latest version of their
Windows drivers. This so-called "technology" provides "the ability to scroll
continuously with a circular motion." This basically means that they have
finally gotten round to implementing a very useful feature which Linux users
have had for over four years.</p>

<p>In some respects proprietary software is way behind <abbr title="Free and Open Source Software">FOSS</abbr> in terms of features
and usability, and this example also shows how proprietary software uses ideas
which were first implemented in <abbr title="Free and Open Source Software">FOSS</abbr>.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>When I first started using Linux four years ago, one of the most useful
features I discovered was circular scrolling on <a href="http://en.wikipedia.org/wiki/Touchpad">touchpads</a>. (For those that
don't know, this allows you to scroll up and down by moving your finger in a
circle.) Traditional scrolling now feels very clumsy, and I find it awkward
when using a laptop which doesn't have this feature (such as those running
Windows). According to the <a href="http://web.telia.com/~u89404340/touchpad/files/changes.txt">changelog</a> for the <a href="http://en.wikipedia.org/wiki/X.Org_Server">XOrg</a>/<a href="http://en.wikipedia.org/wiki/XFree86">XFree86</a> Synaptics
<a href="http://web.telia.com/~u89404340/touchpad/">driver</a>, this feature was added in February 2004.</p>

<p>I happened to come across the <a href="http://lifehacker.com/5057317/synaptics-adds-mac+like-gestures-to-touchpads">news</a> today that <a href="http://en.wikipedia.org/wiki/Synaptics">Synaptics</a> have added a
feature called <em><a href="http://www.synaptics.com/technology/chiral.cfm">ChiralTouch Technology</a></em> to the latest version of their
Windows drivers. This so-called "technology" provides "the ability to scroll
continuously with a circular motion." This basically means that they have
finally gotten round to implementing a very useful feature which Linux users
have had for over four years.</p>

<p>In some respects proprietary software is way behind <abbr title="Free and Open Source Software">FOSS</abbr> in terms of features
and usability, and this example also shows how proprietary software uses ideas
which were first implemented in <abbr title="Free and Open Source Software">FOSS</abbr>.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Vim syntax highlighting for irssi IRC logs</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/10/01/vim-syntax-highlighting-irssi-irc-logs" />
    <id>http://michael.gorven.za.net/blog/2008/10/01/vim-syntax-highlighting-irssi-irc-logs</id>
    <published>2008-10-01T16:19:20+02:00</published>
    <updated>2008-10-01T17:17:20+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="irc" />
    <category term="irssi" />
    <category term="linux" />
    <category term="technical" />
    <category term="vim" />
    <summary type="html"><![CDATA[<p>When I occasionally read <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"><abbr title="Internet Relay Chat">IRC</abbr></a> logs saved by <a href="http://en.wikipedia.org/wiki/Irssi">irssi</a>, I find the lack of
colouring rather annoying and find that I can't read them very quickly. I
finally got round to writing a syntax highlighting plugin for <a href="http://en.wikipedia.org/wiki/Vim_(text_editor)">Vim</a> in order to correct this. The
colours could probably do with some improvement, but it's much better than
before.</p>

<p>In case anyone else finds this useful, I have attached the plugin to this post.
To use it, save <a href="/files/irssilog.vim"><span class="geshifilter"><code class="geshifilter-text">irssilog.vim</code></span></a> in <span class="geshifilter"><code class="geshifilter-text">~/.vim/syntax/</code></span> and enter the following
command to use it with the current file.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">:set syntax=irssilog</pre></div></pre></p>

<p>If you want Vim to automatically detect the file type, add the following to
<span class="geshifilter"><code class="geshifilter-text">~/.vim/ftdetect/irssilog.vim</code></span><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">au BufRead,BufNewFile &lt;em&gt;/irclogs&lt;/em&gt;.log    set filetype=irssilog</pre></div></pre></p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>This relies on the logs being stored in the default location of <span class="geshifilter"><code class="geshifilter-text">~/irclogs/</code></span>.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>When I occasionally read <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"><abbr title="Internet Relay Chat">IRC</abbr></a> logs saved by <a href="http://en.wikipedia.org/wiki/Irssi">irssi</a>, I find the lack of
colouring rather annoying and find that I can't read them very quickly. I
finally got round to writing a syntax highlighting plugin for <a href="http://en.wikipedia.org/wiki/Vim_(text_editor)">Vim</a> in order to correct this. The
colours could probably do with some improvement, but it's much better than
before.</p>

<p>In case anyone else finds this useful, I have attached the plugin to this post.
To use it, save <a href="/files/irssilog.vim"><code>irssilog.vim</code></a> in <code>~/.vim/syntax/</code> and enter the following
command to use it with the current file.</p>

<pre><code>:set syntax=irssilog
</code></pre>

<p>If you want Vim to automatically detect the file type, add the following to
<code>~/.vim/ftdetect/irssilog.vim</code><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.</p>

<pre><code>au BufRead,BufNewFile */irclogs*.log    set filetype=irssilog
</code></pre>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>This relies on the logs being stored in the default location of <code>~/irclogs/</code>.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
  <entry>
    <title>My personal backup solution</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/09/26/my-personal-backup-solution" />
    <id>http://michael.gorven.za.net/blog/2008/09/26/my-personal-backup-solution</id>
    <published>2008-09-26T15:10:02+02:00</published>
    <updated>2008-09-26T15:21:29+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="backup" />
    <category term="encfs" />
    <category term="linux" />
    <category term="pdumpfs" />
    <category term="storebackup" />
    <category term="technical" />
    <category term="ubuntu" />
    <summary type="html"><![CDATA[<p>I've been using an external harddrive to store backups of my laptop for a while
now. At first I manually created a set of compressed <a href="http://en.wikipedia.org/wiki/Tar_(file_format)">tar</a> archives about
once a month. That was a bad system though because it used a lot of space and
was a mission to retrieve files from backups. I then started using <a href="http://0xcc.net/pdumpfs/">pdumpfs</a>,
which can do incremental backups by <a href="http://en.wikipedia.org/wiki/Hard_link">hard linking</a> files which haven't
changed. The problem I found with it however was that if a file's ownership or
timestamps changed it wouldn't be hard linked even if the content hadn't
changed.</p>

<p>I therefore set out to find a better backup solution. My requirements were as
follows.</p>

<ol>
<li>Incremental backups</li>
<li>Easy to access specific files from backups</li>
<li>Able to delete certain backups, preferably arbitrarily<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></li>
<li>Compression</li>
<li>Encryption</li>
</ol>

<p>I finally settled on <a href="http://sourceforge.net/projects/storebackup">storeBackup</a> which supports everything except number 5.
It works similarly to <span class="geshifilter"><code class="geshifilter-text">pdumpfs</code></span>, except it stores ownership and timestamp data
separately and therefore can still hard link identical files even if these
change. It compresses on a per file basis, which makes it easy to access
specific files (as opposed to having to find them in an archive). Old backups
can be deleted arbitrarily since they are only related by hard links. I then
added encryption by backing up to an <a href="http://www.arg0.net/encfs">encfs</a> encrypted directory.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>I want to be able to backup every week, but then delete old backups so
that I have one backup per month for the last year.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>I've been using an external harddrive to store backups of my laptop for a while
now. At first I manually created a set of compressed <a href="http://en.wikipedia.org/wiki/Tar_(file_format)">tar</a> archives about
once a month. That was a bad system though because it used a lot of space and
was a mission to retrieve files from backups. I then started using <a href="http://0xcc.net/pdumpfs/">pdumpfs</a>,
which can do incremental backups by <a href="http://en.wikipedia.org/wiki/Hard_link">hard linking</a> files which haven't
changed. The problem I found with it however was that if a file's ownership or
timestamps changed it wouldn't be hard linked even if the content hadn't
changed.</p>

<p>I therefore set out to find a better backup solution. My requirements were as
follows.</p>

<ol>
<li>Incremental backups</li>
<li>Easy to access specific files from backups</li>
<li>Able to delete certain backups, preferably arbitrarily<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></li>
<li>Compression</li>
<li>Encryption</li>
</ol>

<p>I finally settled on <a href="http://sourceforge.net/projects/storebackup">storeBackup</a> which supports everything except number 5.
It works similarly to <code>pdumpfs</code>, except it stores ownership and timestamp data
separately and therefore can still hard link identical files even if these
change. It compresses on a per file basis, which makes it easy to access
specific files (as opposed to having to find them in an archive). Old backups
can be deleted arbitrarily since they are only related by hard links. I then
added encryption by backing up to an <a href="http://www.arg0.net/encfs">encfs</a> encrypted directory.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>I want to be able to backup every week, but then delete old backups so
that I have one backup per month for the last year.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
  <entry>
    <title>Downloading Google Talk logs</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/08/17/downloading-google-talk-logs" />
    <id>http://michael.gorven.za.net/blog/2008/08/17/downloading-google-talk-logs</id>
    <published>2008-08-17T12:01:14+02:00</published>
    <updated>2008-08-17T16:53:03+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="beautifulsoup" />
    <category term="code" />
    <category term="google" />
    <category term="gtalk" />
    <category term="python" />
    <category term="technical" />
    <summary type="html"><![CDATA[<p>I used <a href="http://en.wikipedia.org/wiki/Google_Apps">Google Apps</a> to host mail for this domain for a while, and wanted to close down the account since I don't use it anymore. Before I did that I wanted to move all the data onto my server. Transferring the emails was fairly straightforward using <a href="http://en.wikipedia.org/wiki/Post_Office_Protocol"><abbr title="Post Office Protocol">POP3</abbr></a>, but I couldn't find a way to download the <a href="http://en.wikipedia.org/wiki/Google_Talk">Google Talk</a> logs. <a href="http://en.wikipedia.org/wiki/Gmail">Gmail</a> handles the logs as emails, but they aren't accessible using either <abbr title="Post Office Protocol">POP3</abbr> or <a href="http://en.wikipedia.org/wiki/Internet_Message_Access_Protocol"><abbr title="Internet Message Access Protocol">IMAP</abbr></a>.</p>

<p>I therefore wrote a <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> script which downloads the logs via the web interface. On <a href="http://jerith.za.net/">Jeremy's</a> <a href="/blog/2008/08/06/cisco-un-clean-access#comment-13">suggestion</a> I used <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> to parse the <a href="http://en.wikipedia.org/wiki/HTML">HTML</a> this time, which worked very well. The script works with both Google Apps and normal Gmail, although my account got locked twice while trying to download the 3500 logs in my account.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>I used <a href="http://en.wikipedia.org/wiki/Google_Apps">Google Apps</a> to host mail for this domain for a while, and wanted to close down the account since I don't use it anymore. Before I did that I wanted to move all the data onto my server. Transferring the emails was fairly straightforward using <a href="http://en.wikipedia.org/wiki/Post_Office_Protocol"><abbr title="Post Office Protocol">POP3</abbr></a>, but I couldn't find a way to download the <a href="http://en.wikipedia.org/wiki/Google_Talk">Google Talk</a> logs. <a href="http://en.wikipedia.org/wiki/Gmail">Gmail</a> handles the logs as emails, but they aren't accessible using either <abbr title="Post Office Protocol">POP3</abbr> or <a href="http://en.wikipedia.org/wiki/Internet_Message_Access_Protocol"><abbr title="Internet Message Access Protocol">IMAP</abbr></a>.</p>

<p>I therefore wrote a <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> script which downloads the logs via the web interface. On <a href="http://jerith.za.net/">Jeremy's</a> <a href="/blog/2008/08/06/cisco-un-clean-access#comment-13">suggestion</a> I used <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> to parse the <a href="http://en.wikipedia.org/wiki/HTML">HTML</a> this time, which worked very well. The script works with both Google Apps and normal Gmail, although my account got locked twice while trying to download the 3500 logs in my account.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Routing by port number</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/08/15/routing-port-number" />
    <id>http://michael.gorven.za.net/blog/2008/08/15/routing-port-number</id>
    <published>2008-08-15T12:35:10+02:00</published>
    <updated>2008-08-15T12:35:10+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="iptables" />
    <category term="linux" />
    <category term="openvpn" />
    <category term="routing" />
    <category term="technical" />
    <category term="ubuntu" />
    <summary type="html"><![CDATA[<p>Due to a very restrictive firewall at the <a href="http://www.chpc.ac.za/"><abbr title="Centre for High Performance Computing">CHPC</abbr></a>, I need to run a <a href="http://en.wikipedia.org/wiki/Virtual_private_network"><abbr title="Virtual Private Network">VPN</abbr></a> to get
access to things like email, <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber</a> and <a href="http://en.wikipedia.org/wiki/Secure_Shell"><abbr title="Secure Shell">SSH</abbr></a>. This however degrades my web
browsing experience, since that gets tunnelled as well. I therefore wanted a
setup where only ports which are blocked get tunnelled through the <abbr title="Virtual Private Network">VPN</abbr>, while
everything else goes out normally.</p>

<p>The routing part was fairly straightforward, which consists of an <a href="http://en.wikipedia.org/wiki/Iptables">iptables</a>
rule to mark certain packets, and an alternate routing table for these marked
packets. I first created a name for the new table by adding the following to
<span class="geshifilter"><code class="geshifilter-text">/etc/iproute2/rt_tables</code></span>.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">10  vpn</pre></div></pre></p>

<p>I then added a default route to the new table specifying the IP address of the
<abbr title="Virtual Private Network">VPN</abbr> server and the <abbr title="Virtual Private Network">VPN</abbr> interface, and a rule to use this table for packets
marked by iptables.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">ip route add default via 10.8.0.3 dev tun0 table vpn
ip rule add fwmark 0x1 table vpn</pre></div></pre></p>

<p>The following iptables rule will mark packets destined to the listed port
numbers. Note that this is for packets originating from the firewall host — if
you want this to apply to packets forwarded for other hosts it must be in the
<span class="geshifilter"><code class="geshifilter-text">PREROUTING</code></span> chain.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">iptables -t mangle -A OUTPUT -p tcp -m multiport --dports 22,995,587,5223 -j MARK --set-mark 0x1</pre></div></pre></p>

<p>The actual routing worked, but packets were being sent with the wrong source IP.
I therefore needed to NAT packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface (the IP address
is the local IP of the <abbr title="Virtual Private Network">VPN</abbr> connection).</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">iptables -t nat -A POSTROUTING -o tun0 -j SNAT --to 10.8.0.4</pre></div></pre></p>

<p>I could then see packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface with the correct source
IP as well as the replies, but it still wasn't working. I eventually discovered
that <span class="geshifilter"><code class="geshifilter-text">rp_filter</code></span> must be disabled in order for this to work.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">echo 0 &amp;gt; /proc/sys/net/ipv4/conf/tun0/rp_filter</pre></div></pre></p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Due to a very restrictive firewall at the <a href="http://www.chpc.ac.za/"><abbr title="Centre for High Performance Computing">CHPC</abbr></a>, I need to run a <a href="http://en.wikipedia.org/wiki/Virtual_private_network"><abbr title="Virtual Private Network">VPN</abbr></a> to get
access to things like email, <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber</a> and <a href="http://en.wikipedia.org/wiki/Secure_Shell"><abbr title="Secure Shell">SSH</abbr></a>. This however degrades my web
browsing experience, since that gets tunnelled as well. I therefore wanted a
setup where only ports which are blocked get tunnelled through the <abbr title="Virtual Private Network">VPN</abbr>, while
everything else goes out normally.</p>

<p>The routing part was fairly straightforward, which consists of an <a href="http://en.wikipedia.org/wiki/Iptables">iptables</a>
rule to mark certain packets, and an alternate routing table for these marked
packets. I first created a name for the new table by adding the following to
<code>/etc/iproute2/rt_tables</code>.</p>

<pre><code>10  vpn
</code></pre>

<p>I then added a default route to the new table specifying the IP address of the
<abbr title="Virtual Private Network">VPN</abbr> server and the <abbr title="Virtual Private Network">VPN</abbr> interface, and a rule to use this table for packets
marked by iptables.</p>

<pre><code>ip route add default via 10.8.0.3 dev tun0 table vpn
ip rule add fwmark 0x1 table vpn
</code></pre>

<p>The following iptables rule will mark packets destined to the listed port
numbers. Note that this is for packets originating from the firewall host — if
you want this to apply to packets forwarded for other hosts it must be in the
<code>PREROUTING</code> chain.</p>

<pre><code>iptables -t mangle -A OUTPUT -p tcp -m multiport --dports 22,995,587,5223 -j MARK --set-mark 0x1
</code></pre>

<p>The actual routing worked, but packets were being sent with the wrong source IP.
I therefore needed to NAT packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface (the IP address
is the local IP of the <abbr title="Virtual Private Network">VPN</abbr> connection).</p>

<pre><code>iptables -t nat -A POSTROUTING -o tun0 -j SNAT --to 10.8.0.4
</code></pre>

<p>I could then see packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface with the correct source
IP as well as the replies, but it still wasn't working. I eventually discovered
that <code>rp_filter</code> must be disabled in order for this to work.</p>

<pre><code>echo 0 &gt; /proc/sys/net/ipv4/conf/tun0/rp_filter
</code></pre>
    ]]></content>
  </entry>
  <entry>
    <title>Photo blogging via email with Drupal</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/08/10/photo-blogging-email-drupal" />
    <id>http://michael.gorven.za.net/blog/2008/08/10/photo-blogging-email-drupal</id>
    <published>2008-08-10T17:12:16+02:00</published>
    <updated>2008-08-10T17:12:16+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="drupal" />
    <category term="photoblogging" />
    <category term="technical" />
    <summary type="html"><![CDATA[<p>The one thing missing from my <a href="http://michael.gorven.za.net/blog/2008/07/07/my-drupal-setup">posting by email</a> setup was support for images. The <a href="http://drupal.org/project/mailsave">Mailsave</a> module has finally been updated for <a href="http://drupal.org/">Drupal 6</a>, and so I can now submit attachments with email posts. The one shortcoming is that files are simply added to posts as normal attachments, and so images aren't automatically displayed. I therefore have to manually insert images in the body of the post, but I actually prefer this since it's a simpler system and gives me more control.</p>

<p>I also needed a way of resizing images on my <a href="http://en.wikipedia.org/wiki/Nokia_E70">phone</a> since they are too big. I found the <a href="http://europe.nokia.com/A4164022?url=http://nds1.nokia.com/phones/files/software/Nokia_3250_ImageEditor.SIS">Nokia Image Editor</a><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> which seems to work fairly well, although it only allows resizing to specific resolutions.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>It does work on my phone even though it's supposedly only for the Nokia 3250.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>The one thing missing from my <a href="http://michael.gorven.za.net/blog/2008/07/07/my-drupal-setup">posting by email</a> setup was support for images. The <a href="http://drupal.org/project/mailsave">Mailsave</a> module has finally been updated for <a href="http://drupal.org/">Drupal 6</a>, and so I can now submit attachments with email posts. The one shortcoming is that files are simply added to posts as normal attachments, and so images aren't automatically displayed. I therefore have to manually insert images in the body of the post, but I actually prefer this since it's a simpler system and gives me more control.</p>

<p>I also needed a way of resizing images on my <a href="http://en.wikipedia.org/wiki/Nokia_E70">phone</a> since they are too big. I found the <a href="http://europe.nokia.com/A4164022?url=http://nds1.nokia.com/phones/files/software/Nokia_3250_ImageEditor.SIS">Nokia Image Editor</a><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> which seems to work fairly well, although it only allows resizing to specific resolutions.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>It does work on my phone even though it's supposedly only for the Nokia 3250.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
  <entry>
    <title>Cisco un-Clean Access</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/08/06/cisco-un-clean-access" />
    <id>http://michael.gorven.za.net/blog/2008/08/06/cisco-un-clean-access</id>
    <published>2008-08-06T11:09:36+02:00</published>
    <updated>2008-08-17T16:54:09+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="chpc" />
    <category term="cisco" />
    <category term="clean access" />
    <category term="code" />
    <category term="linux" />
    <category term="technical" />
    <category term="ubuntu" />
    <summary type="html"><![CDATA[<p>The <a href="http://www.chpc.ac.za/"><abbr title="Centre for High Performance Computing">CHPC</abbr></a> installed a new network this past weekend as part of the <a href="http://www.meraka.org.za/sanren.htm"><abbr title="South African National Research Network">SANReN</abbr></a> project. The new network consists of <a href="http://en.wikipedia.org/wiki/Cisco_Systems">Cisco</a> equipment, including their <a href="http://en.wikipedia.org/wiki/Cisco_NAC_Appliance"><abbr title="Network Admission Control">NAC</abbr></a> (or "Clean Access") system. This requires all clients to authenticate before they are allowed access to the network, and can also enforce a configured security policy (such as requiring operating system updates and anti-virus).</p>

<p>The system works as follows. By default, the ports on the switch are in an "unauthenticated" <a href="http://en.wikipedia.org/wiki/Virtual_LAN"><abbr title="Virtual LAN">VLAN</abbr></a>. When a client is connected, it is provided with an IP address (via <a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol"><abbr title="Dynamic Host Configuration Protocol">DHCP</abbr></a>) in an "unauthenticated" subnet. The system then presents a captive portal which requires the user to authenticate with a username and password using their browser. If the authentication is successful, the port is moved to a different <abbr title="Virtual LAN">VLAN</abbr> (depending on the user's access level), and the switch briefly disconnects the link which causes the client to negotiate a new IP address (in a different subnet).</p>

<p>Before the portal presents the login page it requires that a <a href="http://en.wikipedia.org/wiki/Java_applet">Java applet</a> be run on the client. The applet gathers various bits of information about the client (including the operating system) and submits this information to the portal. (I assume that the portal uses this information to determine what policies must be enforced. In our setup, Windows machines must have the Clean Access Client installed, while Linux and Mac OS X machines are simply allowed access.) The portal then presents the login page.</p>

<p>Being a geek, I wasn't very happy to go through this rigmarole everytime I connected to the network. (I also couldn't use my <a href="http://en.wikipedia.org/wiki/Konqueror">normal browser</a> since the applet didn't work in it.) So I set out to automate the process. Initially I tried to script everything (including the Java applet) but then I noticed that the output of the applet wasn't sent with the login form submission. The only other information the form contained was a session key and random string, both of which were present on the <a href="http://en.wikipedia.org/wiki/HTML"><abbr title="HyperText Markup Language">HTML</abbr></a> page which contained the applet. A manual test confirmed that the login page could be submitted successfully as long as the session key and random string were correct — the applet could be bypassed.</p>

<p>I quickly scripted the login process using a <a href="http://en.wikipedia.org/wiki/Bash">bash</a> script and <a href="http://en.wikipedia.org/wiki/Wget">wget</a>. I then installed it in <span class="geshifilter"><code class="geshifilter-text">/etc/network/if-up.d</code></span> after adding some logic to only execute if the current IP address was on the unauthenticated network. The result is that I can plug in the cable, and my machine automatically authenticates to the system.</p>

<p>While searching for information about the Clean Access system, I came across this <a href="http://it.slashdot.org/article.pl?sid=07/04/27/203232">Slashdot article</a> about a guy who was suspended from university for bypassing the Clean Access checks. I only realised last night that this is exactly what my script does!<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> I haven't tested it on Windows yet, but the only possible change I can think of is to change the <a href="http://en.wikipedia.org/wiki/User_agent">user agent</a>. Seriously Cisco, the fact that I managed to bypass the applet simply by submitting the login form programmatically is ridiculous.</p>

<p>I have attached my script to this post. The way in which I have parsed the <abbr title="HyperText Markup Language">HTML</abbr> page is rather ugly and likely to only work on this specific version of Clean Access. I plan to rewrite it in <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> sometime.</p>

<p><strong>Update:</strong> I have rewritten the script in Python, which should be a bit more solid since it parses the <abbr title="HyperText Markup Language">HTML</abbr> using a <a href="http://en.wikipedia.org/wiki/Document_Object_Model"><abbr title="Document Object Model">DOM</abbr></a>. The script requires <a href="http://www.boddie.org.uk/python/libxml2dom.html">libxml2dom</a> and <a href="http://russell.rucus.net/2008/ipy/">ipy</a>. After configuring the parameters it can be dropped in <span class="geshifilter"><code class="geshifilter-text">/etc/network/if-up.d</code></span><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> where it should run automatically.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>Note that it doesn't bypass the authentication: you still need a valid account in order to gain access.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p>Make sure not to use a dot in the filename though.&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></summary>
    <content type="html"><![CDATA[<p>The <a href="http://www.chpc.ac.za/"><abbr title="Centre for High Performance Computing">CHPC</abbr></a> installed a new network this past weekend as part of the <a href="http://www.meraka.org.za/sanren.htm"><abbr title="South African National Research Network">SANReN</abbr></a> project. The new network consists of <a href="http://en.wikipedia.org/wiki/Cisco_Systems">Cisco</a> equipment, including their <a href="http://en.wikipedia.org/wiki/Cisco_NAC_Appliance"><abbr title="Network Admission Control">NAC</abbr></a> (or "Clean Access") system. This requires all clients to authenticate before they are allowed access to the network, and can also enforce a configured security policy (such as requiring operating system updates and anti-virus).</p>

<p>The system works as follows. By default, the ports on the switch are in an "unauthenticated" <a href="http://en.wikipedia.org/wiki/Virtual_LAN"><abbr title="Virtual LAN">VLAN</abbr></a>. When a client is connected, it is provided with an IP address (via <a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol"><abbr title="Dynamic Host Configuration Protocol">DHCP</abbr></a>) in an "unauthenticated" subnet. The system then presents a captive portal which requires the user to authenticate with a username and password using their browser. If the authentication is successful, the port is moved to a different <abbr title="Virtual LAN">VLAN</abbr> (depending on the user's access level), and the switch briefly disconnects the link which causes the client to negotiate a new IP address (in a different subnet).</p>

<p>Before the portal presents the login page it requires that a <a href="http://en.wikipedia.org/wiki/Java_applet">Java applet</a> be run on the client. The applet gathers various bits of information about the client (including the operating system) and submits this information to the portal. (I assume that the portal uses this information to determine what policies must be enforced. In our setup, Windows machines must have the Clean Access Client installed, while Linux and Mac OS X machines are simply allowed access.) The portal then presents the login page.</p>

<p>Being a geek, I wasn't very happy to go through this rigmarole everytime I connected to the network. (I also couldn't use my <a href="http://en.wikipedia.org/wiki/Konqueror">normal browser</a> since the applet didn't work in it.) So I set out to automate the process. Initially I tried to script everything (including the Java applet) but then I noticed that the output of the applet wasn't sent with the login form submission. The only other information the form contained was a session key and random string, both of which were present on the <a href="http://en.wikipedia.org/wiki/HTML"><abbr title="HyperText Markup Language">HTML</abbr></a> page which contained the applet. A manual test confirmed that the login page could be submitted successfully as long as the session key and random string were correct — the applet could be bypassed.</p>

<p>I quickly scripted the login process using a <a href="http://en.wikipedia.org/wiki/Bash">bash</a> script and <a href="http://en.wikipedia.org/wiki/Wget">wget</a>. I then installed it in <code>/etc/network/if-up.d</code> after adding some logic to only execute if the current IP address was on the unauthenticated network. The result is that I can plug in the cable, and my machine automatically authenticates to the system.</p>

<p>While searching for information about the Clean Access system, I came across this <a href="http://it.slashdot.org/article.pl?sid=07/04/27/203232">Slashdot article</a> about a guy who was suspended from university for bypassing the Clean Access checks. I only realised last night that this is exactly what my script does!<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> I haven't tested it on Windows yet, but the only possible change I can think of is to change the <a href="http://en.wikipedia.org/wiki/User_agent">user agent</a>. Seriously Cisco, the fact that I managed to bypass the applet simply by submitting the login form programmatically is ridiculous.</p>

<p>I have attached my script to this post. The way in which I have parsed the <abbr title="HyperText Markup Language">HTML</abbr> page is rather ugly and likely to only work on this specific version of Clean Access. I plan to rewrite it in <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> sometime.</p>

<p><strong>Update:</strong> I have rewritten the script in Python, which should be a bit more solid since it parses the <abbr title="HyperText Markup Language">HTML</abbr> using a <a href="http://en.wikipedia.org/wiki/Document_Object_Model"><abbr title="Document Object Model">DOM</abbr></a>. The script requires <a href="http://www.boddie.org.uk/python/libxml2dom.html">libxml2dom</a> and <a href="http://russell.rucus.net/2008/ipy/">ipy</a>. After configuring the parameters it can be dropped in <code>/etc/network/if-up.d</code><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> where it should run automatically.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>Note that it doesn't bypass the authentication: you still need a valid account in order to gain access.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p>Make sure not to use a dot in the filename though.&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
    ]]></content>
  </entry>
</feed>
