<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.0.7" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Try before you buy</title>
	<link>http://jc.ngo.org.uk/blog</link>
	<description>It'll all be over in 60 days</description>
	<pubDate>Mon, 10 Sep 2007 03:01:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.7</generator>
	<language>en</language>
			<item>
		<title>WhiBal - easy white balance correction</title>
		<link>http://jc.ngo.org.uk/blog/2007/09/10/whibal-easy-white-balance-correction/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/09/10/whibal-easy-white-balance-correction/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 02:59:47 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>review</category>

		<category>photography</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/09/10/whibal-easy-white-balance-correction/</guid>
		<description><![CDATA[I&#8217;ve taken to carrying around a RawWorkflow WhiBal card when I&#8217;ve been out and about practicing my photography, and had a few people ask me what it&#8217;s for and how it helps.

One of the nice things about how we see is that our brains are adept at adjusting our perception of what we see according [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve taken to carrying around a <a href="http://www.rawworkflow.com/products/whibal/index.html">RawWorkflow WhiBal card</a> when I&#8217;ve been out and about practicing my photography, and had a few people ask me what it&#8217;s for and how it helps.</p>
<div style="text-align:center;"><img style="border: 1px solid black" src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/09//WhiBal_PK_Main-9632_480x320.shkl.jpg" alt="WhiBal_PK_Main-9632_480x320.shkl.jpg" border="0" width="480" height="320" /></div>
<p>One of the nice things about how we see is that our brains are adept at adjusting our perception of what we see according to the lighting conditions.  If we know that something is white we perceive it to be white, and can generally ignore the actual lighting conditions.  For example, if you put on a pair of tinted sunglasses for a few minutes everything appears to take on the tint of the glasses.  And then your brain adjusts, and everything appears to be the normal colour again.</p>
<p>Cameras don&#8217;t do this.<br />
<a id="more-123"></a><br />
For example, shoot a photo in daylight and everything has a blueish tint.  Shoot under indoor lighting and everything looks different.  Shoot with a flash and things change again.  Most cameras do a reasonable job of adapting to this.  Either with a White Balance setting of &#8220;auto&#8221;, or by allowing you to specify the lighting conditions.</p>
<p>However, &#8220;reasonable&#8221; does not equal perfect.  Which is where the WhiBal card comes in.</p>
<p>The WhiBal is an example of a &#8220;grey card&#8221;.  It&#8217;s a very specific, known shade of grey, and many post-processing tools, such as <a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2FAdobe-Systems-Inc-Photoshop-CS3%2Fdp%2FB000O17CQ0%3Fie%3DUTF8%26s%3Dsoftware%26qid%3D1189392851%26sr%3D1-4&#038;tag=trybefoyoub01-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=6738">Photoshop</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=trybefoyoub01-21&amp;l=ur2&amp;o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> or <a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2FAdobe-Photoshop-Lightroom-PC-Mac%2Fdp%2FB000MQCFJQ%3Fie%3DUTF8%26s%3Dsoftware%26qid%3D1189392775%26sr%3D8-1&#038;tag=trybefoyoub01-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=6738">Lightroom</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=trybefoyoub01-21&amp;l=ur2&amp;o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, have a feature whereby you can select a part of the image that you know to be neutral, and it can automatically correct the image&#8217;s white balance.  All you need to do is find a part of the image that&#8217;s supposed to be neutral.</p>
<p>That&#8217;s not always easy.  So what many applications support is the ability to make an exposure change in one  image, and then synchronise that change to one or more other images.</p>
<p>A worked example may make this easier to follow.  Yesterday I was at <a href="http://www.bigbasin.org/">Big Basin Redwoods State Park</a>.  Each time I walked to a different location where the light had changed (because of the varying amount of tree canopy cover) I took a photo of the WhiBal card, and then carried on shooting whatever caught my eye.</p>
<p>After returning, and importing the images in to Lightroom, one of the first tasks is to correct the white balance.  Here&#8217;s one of the photos of the WhiBal card before adjustment.</p>
<div style="text-align:center;"><img style="border: 1px solid black" src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/09/_MG_4444-raw.jpg" alt="_MG_4444-raw.jpg" border="0" width="480" height="320" /></div>
<p>Correcting the white balance for this picture is easy.  Just press &#8220;w&#8221;, which brings up an eye-dropper, and click anywhere in the grey face of the card.  That colour corrects the image to this.</p>
<div style="text-align:center;"><img style="border: 1px solid black" src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/09/_MG_4444-wb.jpg" alt="_MG_4444-wb.jpg" border="0" width="480" height="320" /></div>
<p>Synchronising this colour correction is easy in Lightroom.  Select the first photo (the one that contains the WhiBal card).  It&#8217;s important to select this one first, as Lightroom uses it as the master from which the settings are copied.  Then select all the other photos taken under the same conditions.  Make sure you&#8217;re in the Develop module, and hit the Synchronise button in the bottom right of the interface.</p>
<p>A dialog pops up asking which information you want to sync.  Make sure that only White Balance is selected.</p>
<p>And that takes this:</p>
<div style="text-align:center;"><img style="border: 1px solid black"  src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/09/_MG_4447-raw.jpg" alt="_MG_4447-raw.jpg" border="0" width="480" height="720" /></div>
<p>to this:</p>
<div style="text-align:center;"><img style="border: 1px solid black"  src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/09//_MG_4447-wb.jpg" alt="_MG_4447-wb.jpg" border="0" width="480" height="720" /></div>
<p>This isn&#8217;t a perfect adjustment yet, but it&#8217;s a good start.  One of the things this would benefit from is adjusting the white and black point in the image &#8212; a feature that <a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2FAdobe-Systems-Inc-Photoshop-CS3%2Fdp%2FB000O17CQ0%3Fie%3DUTF8%26s%3Dsoftware%26qid%3D1189392851%26sr%3D1-4&#038;tag=trybefoyoub01-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=6738">Photoshop</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=trybefoyoub01-21&amp;l=ur2&amp;o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> supports but <a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2FAdobe-Photoshop-Lightroom-PC-Mac%2Fdp%2FB000MQCFJQ%3Fie%3DUTF8%26s%3Dsoftware%26qid%3D1189392775%26sr%3D8-1&#038;tag=trybefoyoub01-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=6738">Lightroom</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=trybefoyoub01-21&amp;l=ur2&amp;o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> doesn&#8217;t.  As you can see from the shot of the card, it also includes black and white reference targets which makes these sorts of adjustments very easy too.</p>
<p>Grey cards aren&#8217;t new inventions.  But the WhiBal is a very handy one to carry around, especially in the credit-card sized form factor.</p>
<p class="akst_link"><a href="javascript:void(akst_share('123', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F09%2F10%2Fwhibal-easy-white-balance-correction%2F', 'WhiBal+-+easy+white+balance+correction'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_123">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/09/10/whibal-easy-white-balance-correction/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Smylers&#8217; &#8220;Beginners guide to talking at conferences&#8221;</title>
		<link>http://jc.ngo.org.uk/blog/2007/09/07/smylers-beginners-guide-to-talking-at-conferences/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/09/07/smylers-beginners-guide-to-talking-at-conferences/#comments</comments>
		<pubDate>Fri, 07 Sep 2007 03:53:07 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/09/07/smylers-beginners-guide-to-talking-at-conferences/</guid>
		<description><![CDATA[I ran in to Smylers&#8217; Talking at Conferences: A Beginners&#8217; Guide the other day.  It&#8217;s a very useful distillation of things you should consider if you&#8217;re thinking of giving a talk at a technical conference, such as YAPC Europe 2007, where the talk was delivered.
One recommendation in particular struck me, in re ordering the [...]]]></description>
			<content:encoded><![CDATA[<p>I ran in to Smylers&#8217; <a href="http://use.perl.org/~Smylers/journal/34284">Talking at Conferences: A Beginners&#8217; Guide</a> the other day.  It&#8217;s a very useful distillation of things you should consider if you&#8217;re thinking of giving a talk at a technical conference, such as <a href="http://vienna.yapceurope.org/ye2007/">YAPC Europe 2007</a>, where the talk was delivered.</p>
<p>One recommendation in particular struck me, in re ordering the material in a presentation effectively.</p>
<blockquote><p>But there is one metric which can be applied to a talk safe in the knowledge that following it would have taken exactly the same preparation time: would the talk have been better had exactly the same content been presented but in the reverse order.</p></blockquote>
<p>I&#8217;ll be keeping that in mind next time I have to present something.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('122', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F09%2F07%2Fsmylers-beginners-guide-to-talking-at-conferences%2F', 'Smylers%27+%22Beginners+guide+to+talking+at+conferences%22'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_122">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/09/07/smylers-beginners-guide-to-talking-at-conferences/feed/</wfw:commentRss>
		</item>
		<item>
		<title>TripIt</title>
		<link>http://jc.ngo.org.uk/blog/2007/09/04/tripit/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/09/04/tripit/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 14:20:54 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>review</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/09/04/tripit/</guid>
		<description><![CDATA[If you&#8217;re a frequent (or even semi-frequent) traveller then you may be interested in a website that I&#8217;ve been using for the past few months.
TripIt exists to make it easy to manage one or more travel itineraries, and to share those itineraries with other people (who can be passive viewers, or active collaborators).
Signing up is [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a frequent (or even semi-frequent) traveller then you may be interested in a website that I&#8217;ve been using for the past few months.</p>
<p><a href="http://www.tripit.com/">TripIt</a> exists to make it easy to manage one or more travel itineraries, and to share those itineraries with other people (who can be passive viewers, or active collaborators).</p>
<p>Signing up is easy, requiring the minimum of personal information.  Once you&#8217;ve registered and activated your account you can start adding to your trip itineraries.  It is possible to do this the tedious, manual way, by typing in the details of you trip &#8212; flights, car hire, accommodation bookings, and so on.</p>
<p align="center"><img class="reflect rheight20" id="image109" src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/09/tripit-thumb.png" alt="TripIt, viewing an itinerary" /></p>
<p>However, TripIt has an ace up its sleeve.</p>
<p><a id="more-119"></a></p>
<p>By forwarding the confirmation e-mails that you receive from the airline, travel agent, car rental company, and so on, to a special address @tripit.com from the e-mail address you signed up with, TripIt&#8217;s systems will parse out the relevant details and import them as itinerary items in to your schedule.  You can then amend them as necessary.  This makes adding details a breeze.</p>
<p>As well as details for flights, accommodation, and car rental you can also add (Google) maps to your itinerary, either as simple maps, or as directions, and notes.</p>
<p>The collaboration features are simple but effective.  Enter the e-mail address of someone you want to share the trip details with, and choose whether you want them to be able to view the itinerary, or to be able to add items to it too.  They receive an e-mail with a custom URL allowing them to view/edit the trip details as necessary.  These invitations can be managed by the original trip owner, and rescinded as necessary.  Collaborators can add notes and comments to the itinerary, amend existing events, and add new ones.</p>
<p>For me this feature alone makes TripIt worthwhile.  I no longer need to leave my mother detailed information about my travels around the world (she&#8217;s a mother, of course she worries).  I can just invite her to view the trip details.</p>
<p>TripIt&#8217;s able to include other pertinent information in your itinerary that it gleans from the Internet.  For example, for flights where it can determine the aircraft type it includes links to the relevant pages on <a href="http://www.seatguru.com/">SeatGuru</a>, direct online check-in links, options to check the flight status, a brief display of the weather forecast for the destination, and so forth.</p>
<p>Other useful features include a &#8220;TripThis&#8221; bookmarklet which can be used to grab URLs of interesting pages and automatically add them to the itinerary, a &#8220;Travel Guide&#8221; for your destination, containing information culled from sites such as <a href="http://www.wikipedia.org/">Wikipedia</a> and <a href="http://www.flickr.com/">Flickr</a>, and growing support for &#8220;Friends&#8221; &#8212; not a feature I&#8217;ve used, but they describe as:</p>
<blockquote><p>&#8230; which enables you to connect with other TripIt users. Once connected, you can view an online calendar of each other&#8217;s travel plans so you can keep track of traveling friends or business colleagues. This is the first of many tools that will make TripIt even more useful to organizing your travel&#8230;and organizing your friends too.</p></blockquote>
<p>and TripSearch &#8212; again, not something I&#8217;ve used yet, but it aims to make it easier to find and book flights, hotels, and so forth.</p>
<p>TripIt still has a few issues.</p>
<ul>
<li>It&#8217;s still quite US-centric.  For example, when it imports flight details and displays them on the itinerary it includes the appropriate contact number for the airline.  But this is the always the US contact number, rather than the local one.</li>
<li>There&#8217;s no support for timezones yet &#8212; although this isn&#8217;t as big a problem as I&#8217;d expected.</li>
<li>While there&#8217;s a calendar view of the trip available via the website it&#8217;s not possible to export this (say as iCal format) in to other applications (at least not that I&#8217;ve seen).</li>
</ul>
<p>However, feedback that I&#8217;ve submitted to the developers has been responded to promptly, and I&#8217;ve seen features that I&#8217;ve suggested appear on the site quite rapidly, so it&#8217;s entirely possible that these issues will be addressed soon.</p>
<p>Despite these few shortcomings TripIt has proved to be very useful, both in allowing me to easily organise my travel details, and in making it very easy to share these with other people.  It also makes it simple to print out a detailed itinerary that contains all the relevant information, which is much nicer than carrying around print outs of half a dozen different confirmation e-mails which all have their information in different formats.</p>
<p>TripIt&#8217;s service is free, and they are still in invitation-only beta mode.  I have two invites left, and the first two people to request an invite in the comments can have them &#8212; just leave your e-mail address.</p>
<p><i>Update: shortly after posting this I received an e-mail from TripIt with another 30 invites.  So don&#8217;t be shy in asking if you think it might be useful.</i>
</p>
<p class="akst_link"><a href="javascript:void(akst_share('119', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F09%2F04%2Ftripit%2F', 'TripIt'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_119">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/09/04/tripit/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Spam false positives from British Airways</title>
		<link>http://jc.ngo.org.uk/blog/2007/08/21/spam-false-positives-from-british-airways/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/08/21/spam-false-positives-from-british-airways/#comments</comments>
		<pubDate>Tue, 21 Aug 2007 07:42:26 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>spam</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/08/21/spam-false-positives-from-british-airways/</guid>
		<description><![CDATA[I note that British Airways e-receipt e-mails are probably going astray for a lot of people.
I&#8217;ve had to book a few flights with BA recently.  Up until a couple of weeks ago their acknowledgment e-mails came through fine.  And then I stopped receiving them.  Taking the time to delve in to the [...]]]></description>
			<content:encoded><![CDATA[<p>I note that <a href="http://www.britishairways.com/">British Airways</a> e-receipt e-mails are probably going astray for a lot of people.</p>
<p>I&#8217;ve had to book a few flights with BA recently.  Up until a couple of weeks ago their acknowledgment e-mails came through fine.  And then I stopped receiving them.  Taking the time to delve in to the mail logs yesterday I noticed this:</p>
<pre>Aug 20 07:47:45 jc sm-mta[15347]: l7KElEmk015347: ruleset=check_mail, 
&nbsp;&nbsp;arg1=website +LHS=RHS@bounce.baplc.com, 
&nbsp;&nbsp;relay=ceba-mgw04.baplc.com [163.166.43.64], 
&nbsp;&nbsp;reject=553 5.1.8 website +LHS=RHS@bounce.baplc.com&#46;.. 
&nbsp;&nbsp;Domain of sender address website+LHS=RHS@bounce.baplc.com does not exist</pre>
<p>(I&#8217;ve redacted the left and right hand side of the actual e-mail address it was being sent to)</p>
<p>If that&#8217;s just so much gibberish to you, it says that BA are sending e-mails with a return path of &#8230;@bounce.baplc.com.  Working through the logs shows that they&#8217;ve been doing this for some time.</p>
<p>But at some point in the last few weeks, someone at BA has removed the bounce.baplc.com entry from their DNS.  So my, and countless other systems around the world, will begin rejecting messages.</p>
<p>This rejection is quite correct.  Since bounce.baplc.com doesn&#8217;t exist, my system (and any other system with the same configuration) will have nowhere to send any bounces that might occur. And sending messages from domains that do not exist is also an exceedingly common spammer tactic.</p>
<p>I&#8217;ve used the &#8220;Report problems with our site&#8221; feature to report this to BA, but I don&#8217;t have high hopes of anyone listening.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('118', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F08%2F21%2Fspam-false-positives-from-british-airways%2F', 'Spam+false+positives+from+British+Airways'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_118">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/08/21/spam-false-positives-from-british-airways/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Holy crap, I&#8217;m moving to Switzerland!</title>
		<link>http://jc.ngo.org.uk/blog/2007/08/02/off-to-switzerland/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/08/02/off-to-switzerland/#comments</comments>
		<pubDate>Thu, 02 Aug 2007 22:10:32 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>google</category>

		<category>flickr</category>

		<category>switzerland</category>

		<category>zurich</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/08/02/off-to-switzerland/</guid>
		<description><![CDATA[It&#8217;s been a bit quiet around here for the last couple of months.  A quick brain dump.
In February I left my job helping to run the mail systems at Citigroup, having sorted myself out with a contracting role doing software development in Perl (with some Autosys and Murex mangling on the side) for the [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a bit quiet around here for the last couple of months.  A quick brain dump.</p>
<p>In February I left my job helping to run the mail systems at <a href="http://www.citigroup.com/">Citigroup</a>, having sorted myself out with a contracting role doing software development in <a href="http://www.perl.org/">Perl</a> (with some <a href="http://www.leyton.org/diary/2005/04/08/whither-autosys/">Autosys</a> and <a href="http://www.murex.com/home.php">Murex</a> mangling on the side) for the nice people at <a href="http://www.brevanhoward.com/">Brevan Howard</a>.  Quite definitely some of the nicest people I&#8217;ve had the pleasure of working with in the financial industry.  If you&#8217;re a <a href="http://london.pm.org/">London-based Perl developer</a> looking for work and the opportunity for a contract with them comes up, jump at it.</p>
<p>Along the way I finally got around to sorting myself out with a <a href="http://www.flickr.com/">Flickr</a> account, and you can see my photos at <a href="http://www.flickr.com/photos/nikclayton/">http://www.flickr.com/photos/nikclayton/</a>.  Not something I&#8217;ve written much about, but that may change in the future.</p>
<p>Anyway, that proved to be temporary.  No, they didn&#8217;t fire me.  Instead, in two days time I jump on a plane bound for Zurich, to start working as a site reliability engineer for <a href="http://www.google.ch">Google Switzerland</a>.</p>
<p>I was over there a couple of weeks ago as part of a preview-cum-orientation trip, which coincided with the once-every-three-years Züri Fäscht (Zurich Festival), so I took the opportunity to snap a few shots of fireworks.</p>
<p><a href="http://www.flickr.com/photos/nikclayton/897795290/" title="Photo Sharing"><img src="http://farm2.static.flickr.com/1339/897795290_52211ffeaa_m.jpg" width="240" height="160" alt="Züri Fäscht" /></a></p>
<p><a href="http://www.flickr.com/photos/nikclayton/897135585/" title="Photo Sharing"><img src="http://farm2.static.flickr.com/1130/897135585_10dcc9effa_m.jpg" width="240" height="160" alt="Züri Fäscht" /></a></p>
<p><a href="http://www.flickr.com/photos/nikclayton/897983670/" title="Photo Sharing"><img src="http://farm2.static.flickr.com/1250/897983670_fe3c922b2e_m.jpg" width="240" height="160" alt="Züri Fäscht" /></a></p>
<p>Anyway, I hope to write more next week about the process, useful sites for people undergoing a similar move, and so on.  That, and getting back to contributing to projects like <a href="http://subversion.tigris.org/">Subversion</a> &#8212; my free time has been practically non-existent for the past 4 months or so, and that&#8217;s something that I&#8217;ve let slip.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('117', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F08%2F02%2Foff-to-switzerland%2F', 'Holy+crap%2C+I%27m+moving+to+Switzerland%21'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_117">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/08/02/off-to-switzerland/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Issues with SPF and Korean ISPs</title>
		<link>http://jc.ngo.org.uk/blog/2007/02/28/issues-with-spf-and-korean-isps/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/02/28/issues-with-spf-and-korean-isps/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 09:16:40 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>spam</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/02/28/issues-with-spf-and-korean-isps/</guid>
		<description><![CDATA[If you publish SPF records, send mail to Korean ISPs, and use SPF mechnisms other than ip4:, you may face a problem.

Apparently (and this is second-hand, so treat it with some caution), the Korean Information Security Agency (KISA) is producing an RBL of domains to blacklist.  This is complemented by a whitelist, called WhiteDomain, [...]]]></description>
			<content:encoded><![CDATA[<p>If you publish <a href="http://www.openspf.org/">SPF records</a>, send mail to Korean ISPs, and use SPF mechnisms other than <tt>ip4:</tt>, you may face a problem.</p>
<p><a id="more-116"></a></p>
<p>Apparently (and this is second-hand, so treat it with some caution), the <a href="http://www.kisa.or.kr/maine.jsp">Korean Information Security Agency</a> (KISA) is producing an RBL of domains to blacklist.  This is complemented by a whitelist, called WhiteDomain, seeded by using published SPF records.</p>
<p>There&#8217;s a webpage for the <a href="https://www.kisarbl.or.kr/">KISA RBL</a>, with both English and Korean versions.  It looks like there&#8217;s more content on the Korean version than on the English version,  but most of it&#8217;s text on images which Google can&#8217;t translate, and my Korean&#8217;s not up to much.</p>
<p>Many Korean ISPs are using this RBL and whitelist </p>
<p>However, the process for seeding WhiteDomain is only correctly handling SPF records that use the <tt>ip4:</tt> mechanism.  Other mechanisms (like <tt>a:</tt>, <tt>ptr:</tt>, and <tt>mx:</tt>) are being ignored.  So if your SPF record doesn&#8217;t use the <tt>ip4:</tt> mechanism (and there are many legitimate reasons for not doing so) you are going to find your e-mail blacklisted by many Korean ISPs.</p>
<p>This is broken for a couple of reasons.  First, the <a href="http://www.openspf.org/RFC_4408">SPF specification</a> is <a href="http://www.openspf.org/RFC_4408#function">quite clear</a> about what a conforming SPF implementation must do:</p>
<blockquote><p>4. The check_host() Function</p>
<p>The check_host() function fetches SPF records, parses them, and interprets them to determine whether a particular host is or is not permitted to send mail with a given identity. Mail receivers that perform this check MUST correctly evaluate the check_host() function as described here.</p></blockquote>
<p>An implemenation that claims to process SPF, but that does not follow parts of the specification is broken, pure and simple.</p>
<p>Second, there&#8217;s nothing preventing spammers from publishing their own SPF records, authorizing their mail relay.  If WhiteDomain is being seeded purely by SPF (and I don&#8217;t know for certain that it is, so take this with an appropriately sized piece of salt) it&#8217;s likely to become less and less useful over time.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('116', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F02%2F28%2Fissues-with-spf-and-korean-isps%2F', 'Issues+with+SPF+and+Korean+ISPs'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_116">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/02/28/issues-with-spf-and-korean-isps/feed/</wfw:commentRss>
		</item>
		<item>
		<title>M-x ecb-activate</title>
		<link>http://jc.ngo.org.uk/blog/2007/02/27/m-x-ecb-activate/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/02/27/m-x-ecb-activate/#comments</comments>
		<pubDate>Tue, 27 Feb 2007 11:11:59 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>emacs</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/02/27/m-x-ecb-activate/</guid>
		<description><![CDATA[I&#8217;m a long time (x)emacs user.  I use vi for small day-to-day stuff (vi TODO, anyone?), but as far as possible I do any development work with emacs, and have done for the past 12 years.
So, a few days ago I was pleased to discover a new mode that I&#8217;d not previously known about.

ecb, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a long time <a href="http://www.xemacs.org/">(x)emacs</a> user.  I use vi for small day-to-day stuff (<tt>vi TODO</tt>, anyone?), but as far as possible I do any development work with emacs, and have done for the past 12 years.</p>
<p>So, a few days ago I was pleased to discover a new mode that I&#8217;d not previously known about.</p>
<p><a id="more-111"></a></p>
<p><a href="http://ecb.sourceforge.net/">ecb</a>, the <a href="http://ecb.sourceforge.net/">Emacs Code Browser</a> is a minor mode that makes browsing a collection of source code easier.  Activate it (assuming it&#8217;s installed) with <tt>M-x ecb-activate</tt>.  It defaults to creating four new buffers within the current window.  These buffers are displayed next to your primary editing buffer.</p>
<p><iframe src="http://rcm-uk.amazon.co.uk/e/cm?t=trybefoyoub01-21&#038;o=2&#038;p=13&#038;l=st1&#038;mode=books&#038;search=emacs&#038;fc1=000000&#038;lt1=&#038;lc1=3366FF&#038;bg1=FFFFFF&#038;f=ifr" marginwidth="0" marginheight="0" width="468" height="60" border="0" frameborder="0" style="border:none;" scrolling="no"></iframe></p>
<p>The first shows a directory tree view of the filesystem, centred at whichever directory contains the currently open file.  The second shows a list of all the files in the currently selected directory.  The third shows a list of all the items of interest in the current file (I&#8217;ll come back to that in a moment).  The fourth shows a list of the currently open files.</p>
<p>The third pane, which shows items of interest, is particularly useful.  Here&#8217;s a screenshot, where I&#8217;ve got a number of .c files open for editing.</p>
<p align="center"><a href="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/02/ecb1.png"><small>Click to enlarge</small><br /><img class="reflect rheight20" id="image109" src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/02/ecb1-thumb.png" alt="ecb with a .c file" /></a></p>
<p>That third pane (mostly green in the thumbnail) is a list of all the functions (along with their type signature) in the file.  Selecting one of those functions jumps to its definition in the file, and makes navigating large source files much easier.</p>
<p>The list of interesting items is not limited to just function definitions.  In this screenshot I&#8217;m in the middle of editing a Perl module (<tt>.pm</tt>).</p>
<p align="center"><a href="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/02/ecb2.png"><small>Click to enlarge</small><br /><img class="reflect rheight20" id="image110" src="http://jc.ngo.org.uk/blog/wp-content/uploads/2007/02/ecb2-thumb.png" alt="ecb with a .pm file" /></a></p>
<p>As well as containing functions, the list now contains information about documentation in the file (in POD format), and package declarations.  Again, this making zipping around the file much easier than repeatedly seaching for &#8220;<tt>sub foo {</tt>&#8220;.</p>
<p>I&#8217;m still scratching the surface of what ecb can do though.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('111', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F02%2F27%2Fm-x-ecb-activate%2F', 'M-x+ecb-activate'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_111">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/02/27/m-x-ecb-activate/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Sendmail 8.14.0: Logging the GreetPause firing time</title>
		<link>http://jc.ngo.org.uk/blog/2007/02/10/sendmail-8140-logging-the-greetpause-firing-time/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/02/10/sendmail-8140-logging-the-greetpause-firing-time/#comments</comments>
		<pubDate>Sat, 10 Feb 2007 10:17:18 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>sendmail</category>

		<category>perl</category>

		<category>spam</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/02/10/sendmail-8140-logging-the-greetpause-firing-time/</guid>
		<description><![CDATA[Following on from yesterday&#8217;s discussion of new features in Sendmail 8.14.0, today I&#8217;m writing about Sendmail&#8217;s GreetPause feature, and some additional logging for it that&#8217;s been added in Sendmail 8.14.0.

Sendmail has supported pausing before displaying the greeting as an anti-spam measure since 8.13.0.
To use it, add a line like:
FEATURE(`greet_pause&#039;, `10000&#039;)
to your sendmail.mc file, and rebuild [...]]]></description>
			<content:encoded><![CDATA[<p>Following on from <a href="http://jc.ngo.org.uk/blog/2007/02/08/sendmail-8140-heloname/">yesterday&#8217;s discussion of new features in Sendmail 8.14.0</a>, today I&#8217;m writing about Sendmail&#8217;s GreetPause feature, and some additional logging for it that&#8217;s been added in Sendmail 8.14.0.</p>
<p><a id="more-108"></a></p>
<p>Sendmail has supported <a href="http://en.wikipedia.org/wiki/Anti-spam_techniques_%28e-mail%29#Greeting_delay">pausing before displaying the greeting</a> as an anti-spam measure since <a href="http://www.sendmail.org/releases/8.13.0.html#RS">8.13.0</a>.</p>
<p>To use it, add a line like:</p>
<pre>FEATURE(`greet_pause&#039;, `10000&#039;)</pre>
<p>to your <tt>sendmail.mc</tt> file, and rebuild the <tt>sendmail.cf</tt> file.  The delay is specified in milliseconds, so that example will cause Sendmail to delay for 10 seconds before displaying the greeting banner.</p>
<p>What that feature was introduced, Sendmail would log connections that fell foul of this check with this line:</p>
<p><tt>rejecting commands from <i>host</i> [<i>ip-addr</i>] due to pre-greeting traffic</tt></p>
<p>This is helpful in determining how many times the check fired (and therefore how many connections it&#8217;s stopping).  The hostname and IP address information can also be mined from the logs and used to update any blacklists or firewall rules you&#8217;re maintaining &#8212; if the site is going to trigger this block then you may as well prevent from connecting, and save some connection slots.</p>
<p>However, it doesn&#8217;t tell give you any idea of what would happen if you were to increase or decrease the greeting pause time.  Suppose you have the delay set to 10 seconds.  It may be the case that all the violators are trying to send data within the first second.  In which case a 10 second delay is going to penalise all connections for an unnecessary 9 seconds.</p>
<p>On the other hand, it might be the case that blocks because of a 10 second greet pause delay are spread out over the entire 10 seconds.  In which case there isn&#8217;t much opportunity to reduce the delay, and it could be argued that increasing the delay makes sense.</p>
<p>To be able to answer questions like this I sent in a patch, and from Sendmail 8.14.0 (or 8.13.5 if you enabled the _FFR_LOG_GREET_PAUSE feature) Sendmail now reports:</p>
<p><tt>rejecting commands from <i>host</i> [<i>ip-addr</i>] due to pre-greeting traffic after <i>num</i> seconds</tt></p>
<p>This is sufficient information to produce a histogram that shows the frequency of the delay at the time that connections are rejected because they triggered this check.  Here&#8217;s an example of what such a report might look like.</p>
<pre># == 1 connection
 Delay&nbsp;&nbsp; Count&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Histogram
&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp;12)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;############
&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp; 9)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#########
&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp;14)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;##############
&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp; 9)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#########
&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp;11)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###########
&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp;27)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###########################
&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp; 8)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;########
&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp;13)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#############
&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp; 6)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;######
&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;&nbsp;(&nbsp;&nbsp;&nbsp;&nbsp;11)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###########</pre>
<p>In this example it&#8217;s clear that the pre-greeting checks are firing evenly across the range of delays &#8212; with the exception at 5 seconds.  There&#8217;s a definite spike there.  That could be inidicative of a particular popular piece of spam-ware that&#8217;s configured to only wait 5 seconds before sending mail.</p>
<p>Here&#8217;s the Perl script that produced that report.  Happy spam hunting.</p>
<pre>#!/usr/bin/perl
&nbsp;
use strict;
use warnings;
&nbsp;
use List::Util qw(max);
&nbsp;
# Read maillog from stdin, produce histogram showing greetpause
# distribution
&nbsp;
my %pauses&nbsp;&nbsp;&nbsp;&nbsp;= ();
my $max_count = 0;
&nbsp;
while(&lt;&gt;) {
&nbsp;&nbsp;&nbsp;&nbsp;next unless $_ =~ /pre-greeting traffic after (\d+) seconds/;
&nbsp;&nbsp;&nbsp;&nbsp;$pauses{$1}++;
&nbsp;&nbsp;&nbsp;&nbsp;$max_count = max($pauses{$1}, $max_count);
}
&nbsp;
my $scale = int($max_count / 40) + 1;
&nbsp;
print &quot;# == $scale connection&quot;, $scale == 1 ? &#039;&#039; : &#039;s&#039;, &quot;n&quot;;
&nbsp;
print &quot; Delay\t Count\t\tHistogramn&quot;;
foreach my $delay (sort keys %pauses) {
&nbsp;&nbsp;&nbsp;&nbsp;printf &quot;%6d\t(%6d)\t%s\n&quot;, $delay, $pauses{$delay},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;#&#039; x ($pauses{$delay} / $scale);
}</pre>
<p class="akst_link"><a href="javascript:void(akst_share('108', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F02%2F10%2Fsendmail-8140-logging-the-greetpause-firing-time%2F', 'Sendmail+8.14.0%3A+Logging+the+GreetPause+firing+time'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_108">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/02/10/sendmail-8140-logging-the-greetpause-firing-time/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Sendmail 8.14.0: HeloName</title>
		<link>http://jc.ngo.org.uk/blog/2007/02/08/sendmail-8140-heloname/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/02/08/sendmail-8140-heloname/#comments</comments>
		<pubDate>Thu, 08 Feb 2007 08:47:43 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>sendmail</category>

		<category>spam</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/02/08/sendmail-8140-heloname/</guid>
		<description><![CDATA[Sendmail 8.14.0 was recently released, and it includes a small handful of patches that I sent in.  The documentation explains what these options do, but doesn&#8217;t explain why you might want to use them.  So I thought I&#8217;d do that in a series of entries here.
First, the new HeloName option.

When Sendmail needs to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sendmail.org/releases/8.14.0.php">Sendmail 8.14.0</a> was recently released, and it includes a small handful of patches that I sent in.  The documentation explains what these options do, but doesn&#8217;t explain why you might want to use them.  So I thought I&#8217;d do that in a series of entries here.</p>
<p>First, the new <tt>HeloName</tt> option.</p>
<p><a id="more-107"></a></p>
<p>When Sendmail needs to deliver mail to a different server, it connects to the remote server, waits for it to send the greeting banner, and then sends:</p>
<pre>HELO the.host.name</pre>
<p>(or <tt>EHLO the.host.name</tt>, but I&#8217;m keeping this simple).  Sendmail uses the local, fully qualified hostname of the host when it does this.  So if you host is called <tt>foo.example.com</tt> Sendmail will send <tt>HELO foo.example.com</tt>.</p>
<p>What happens next depends on how the remote system is configured.  It is very typical for the remote site to do a <a href="http://www.sendmail.org/releases/8.14.0.php">DNS lookup on the provided hostname</a>, to make sure that it exists.  This is a common anti-spam measure.  If the given hostname doesn&#8217;t exist then the rest of the connection will be rejected.</p>
<p>Further, it&#8217;s also common to do the <a href="http://en.wikipedia.org/wiki/Anti-spam_techniques_(e-mail)#PTR.2FReverse_DNS_checks">reverse lookup</a>.  So if <tt>foo.example.com</tt> resolves to the IP address 1.2.3.4, the remote site will then look up <tt>4.3.2.1.in-addr.arpa</tt>, and verify that that resolves back to <tt>foo.example.com</tt>.  Again, if it doesn&#8217;t, the connection is refused.  This is a less common anti-spam technique, but it&#8217;s still found in regular use at hundreds of thousands of sites around the world.</p>
<p>You&#8217;ve probably worked out how this can cause problems.  It&#8217;s common, especially in corporate environments, for hosts to have multiple hostnames, especially if they are internet facing hosts.  There&#8217;ll be one name by which the host is known internally (and is only published in the internal, corporate DNS), and one name (and associated IP address) by which the host is known externally.</p>
<p>This can lead to situations where the mail server connects to the remote server, and sends:</p>
<pre>HELO my.internal.name</pre>
<p><tt>my.internal.name</tt> is not published in the public DNS, so the remote server rejects the rest of the connection.</p>
<p>It may be even more complicated than that &#8212; for example, the internet facing mail relay might be behind a firewall that carries out Network Address Translation (NAT) &#8212; in which case, even if the server is configured to use the correct hostname in the HELO step, that hostname might not resolve back to the right IP address, and again, the connection may be refused.</p>
<p>Prior to the <tt>HeloName</tt> option being added to Sendmail you could use the <tt>confDOMAIN_NAME</tt> configuration option to specify the full domain name to use.</p>
<p>This works, but has other side-effects.  In particular, the value of <tt>confDOMAIN_NAME</tt> appears in <tt>Received:</tt> headers, and if you set it obscures the actual hostname, which can make analysis of messages through the <tt>Received:</tt> headers more difficult.</p>
<p>This is the situation I ran in to at $work.  We have many Internet facing mail servers relaying mail to the outside world.  Each server knows its own internal hostname, but has no knowledge of the hostname it presents to the outside world, nor does it know the IP address that the packets it sends will finally have (all the servers are behind NAT devices).</p>
<p>I considered configuring each server with this information, but decided that that would be a bad idea.  It would have meant tightly coupling our configuration information with configuration information maintained by an entirely separate group (the Networks Team).  Should they decide to renumber a NAT&#8217;d IP address they would need to ensure that we were informed, and that the change was co-ordinated.</p>
<p>That&#8217;s extra work, extra complexity, and extra opportunity for things to go wrong.</p>
<p>Each server&#8217;s IP address is already in a large A record, <tt>mail.example.com</tt>.  I considered adjusting <tt>confDOMAIN_NAME</tt> and related settings so that each outbound mail relay considered itself to be <tt>mail.example.com</tt>, but rejected that idea on the previously mentioned issues relating to <tt>Received:</tt> lines and the extra complexity it introduces when debugging.</p>
<p>So, plan C.  Specifically, I wrote a small patch for Sendmail that introduces a new configuration option, <tt>HeloName</tt>.  If set, Sendmail will use the value of this option when it sends <tt>HELO/EHLO</tt>, instead of the fully qualified hostname (or <tt>confDOMAIN_NAME</tt> setting).</p>
<p>Our Sendmail configuration files now contain this directive:</p>
<pre>define(`confHELO_NAME&#039;, `mail.example.com&#039;)</pre>
<p>This is sufficient for all our outbound mail relays to <tt>HELO</tt> with the same name.  This name contains all their IP addresses.  And the <tt>Received:</tt> headers still contain the correct internal hostnames, to make troubleshooting easier.</p>
<p>If we&#8217;d been using a closed source MTA this wouldn&#8217;t have been possible.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('107', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F02%2F08%2Fsendmail-8140-heloname%2F', 'Sendmail+8.14.0%3A+HeloName'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_107">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/02/08/sendmail-8140-heloname/feed/</wfw:commentRss>
		</item>
		<item>
		<title>More adventures with VMWare</title>
		<link>http://jc.ngo.org.uk/blog/2007/02/01/more-adventures-with-vmware/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/02/01/more-adventures-with-vmware/#comments</comments>
		<pubDate>Thu, 01 Feb 2007 21:05:12 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>solaris</category>

		<category>freebsd</category>

		<category>kubuntu</category>

		<category>vmware</category>

		<category>linux</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/02/01/more-adventures-with-vmware/</guid>
		<description><![CDATA[Well that Kubuntu experimentation didn&#8217;t last long.

After my last post I proceeded to install VMWare Server in Kubuntu. That went relatively easily, and I prepared a Windows XP VMWare image.
The image creation was also relatively smooth, although it took 2 or 3 times longer than a normal Windows install.  For some reason anything involving [...]]]></description>
			<content:encoded><![CDATA[<p>Well that Kubuntu experimentation didn&#8217;t last long.</p>
<p><a id="more-106"></a></p>
<p>After my last post I proceeded to install VMWare Server in Kubuntu. That went relatively easily, and I prepared a Windows XP VMWare image.</p>
<p>The image creation was also relatively smooth, although it took 2 or 3 times longer than a normal Windows install.  For some reason anything involving disk access (so, most of the installation) seemed to stall at various points.</p>
<p>Anyway, with Windows installed I then went on to install <a href="http://en.wikipedia.org/wiki/Steam_%28content_delivery%29">Steam</a> and <a href="http://en.wikipedia.org/wiki/Half_life_2">Half-Life 2</a> from the installation DVD.  Again, there&#8217;s nothing special to write home about that process, and Steam went and downloaded the many megabytes of updates that have accumulated since the last time I played Half-Life 2 (2+ years ago).</p>
<p>By this point my hopes had been raised pretty high.  Sadly, they were to be dashed.  Although Steam was apparently running successfully, attempting to launch any of the games would turn the (Windows) cursor in to an hourglass for a few moments.  There&#8217;d be a bit of disk thrashing.  And then the hourglass returned to a pointer.  Other than that there was no sign of any activity to indicate that the game had started (or might be about to start).</p>
<p>So I looked at alternative solutions.  I found this <a href="Ihttp://ubuntuforums.org/archive/index.php/t-184509.html">forum post about Windows games on Ubuntu</a> that had some pointers.  I tried <a href="http://www.winegq.org">Wine</a>. However, although the installation seemed to go well, and I could use it to run simple Windows apps (<tt>wordpad.exe</tt>, et al), it didn&#8217;t do anything when asked to run the Half-Life 2 installer &#8212; it just returned almost immediately to the command line with no apparent error messages.</p>
<p>I briefly considered <a href="http://transgaming.org/gamesdb/">Cedega</a>.  But that&#8217;s pay-ware, and their <a href="http://downloads.transgaming.com/files/cedega-5.2.10-releasenotes.html#halflife_2">online compatability database</a> suggests that there are still some problems running Half-Life 2.</p>
<p>So, plan B.</p>
<p>I&#8217;ve ditched Kubuntu, and instead installed Windows as the primary OS on the machine.  I&#8217;ve got VMWare Server for Windows installed now, and I&#8217;m installing FreeBSD 6.2 and Solaris 10 virtual machines so that I can pick up the DTrace work from where I left off.</p>
<p>The Windows installation was something of a palavar.  My original Windows XP CD is old.  So old it predates Service Pack 1, never mind Service Pack 2.  Amongst other things this means that the installer doesn&#8217;t recognise disks large than 128GB.  Since the Ultra 40 has a 250GB disk this would have required me to partition the disk, something I&#8217;m loathe to do.</p>
<p>After first installing Windows I experimented with the Disk Management Tool to see if I could grow the partition (after installing SP2). However, that failed, with an error explaining that this wasn&#8217;t possible because the disk had originally been partitioned by an older version of XP.</p>
<p>So I did some digging on the web and turned up <a href="http://www.neowin.net/forum/index.php?showtopic=223562&#038;st=300">Autostreamer</a>.<br />
In a nutshell, this takes your existing, pre-SP2 install disc, a copy of SP2, and creates a new XP install disc with SP2 installed.  Booting from this I was able to create a partition that spanned the entire disk, and install XP SP2.</p>
<p>So in the prior 48 hours I&#8217;d managed to install XP 3 times &#8212; once in to VMWare, once from a pre-SP1 image, and finally from an SP2 image. Frankly, that&#8217;s enough for my lifetime.</p>
<p>Oh, and Half-Life 2 is now installed.  So I&#8217;ve had a happy few hours spent blasting Combine too.  Now if only they&#8217;d hurry up and release Team Fortress 2.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('106', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F02%2F01%2Fmore-adventures-with-vmware%2F', 'More+adventures+with+VMWare'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_106">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/02/01/more-adventures-with-vmware/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting started with Kubuntu</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/28/getting-started-with-kubuntu/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/28/getting-started-with-kubuntu/#comments</comments>
		<pubDate>Sat, 27 Jan 2007 23:21:34 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>solaris</category>

		<category>sun</category>

		<category>freebsd</category>

		<category>kubuntu</category>

		<category>vmware</category>

		<category>linux</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/28/getting-started-with-kubuntu/</guid>
		<description><![CDATA[The Ultra 40 that I won arrived on Wednesday, but I&#8217;ve been too busy since then to do much with it until now.
I have spent a little bit of time carrying out some research.  My initial plan was to triple boot this server.  First as a FreeBSD machine &#8212; it&#8217;s my preferred Unix [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.sun.com/desktop/workstation/ultra40/specs.xml">Ultra 40</a> that <a href=" http://jc.ngo.org.uk/blog/2006/10/27/i-didnt-win/">I won</a> arrived on Wednesday, but I&#8217;ve been too busy since then to do much with it until now.</p>
<p>I have spent a little bit of time carrying out some research.  My initial plan was to triple boot this server.  First as a <a href="http://www.freebsd.org/">FreeBSD</a> machine &#8212; it&#8217;s my preferred Unix flavour, my other Unix boxes run FreeBSD, and it gives me the opportunity to carry out FreeBSD testing on a 64 bit platform.</p>
<p>Then with <a href="http://www.sun.com/software/solaris/">Solaris 10</a>.  I want to carry on the work that I&#8217;ve already started with DTrace, and get some more experience with other Solaris technologies.</p>
<p>Finally, as a Windows XP box.  Two reasons for this.  First, Photoshop.  I take quite a lot of pictures, and, not currently having a Dual Core Mac to hand, Photoshop on XP is my preferred image editing system.  I also have something of a workflow built around it.  The other reason is games.  I don&#8217;t get much opportunity, but when it arises I can quite happily while away the time playing Half Life 2.</p>
<p>That&#8217;s not quite what happened.</p>
<p><a id="more-105"></a></p>
<p>I was happy with the triple boot idea as I already have a primary desktop (a somewhat venerable 2&#215;1GHz PIII), so the hassle of triple booting wasn&#8217;t going to be too much of a problem.  Unfortunately, about 2 weeks ago this desktop decided to give up the ghost, with three hard disks in it failing in fairly short order.</p>
<p>A colleague at work has been talking about <a href="http://www.vmware.com/">VMWare</a> for some time, and has it running on his (Linux) laptop.  I&#8217;d seen it in action a few times, so a new plan started to form.</p>
<p>Specifically, I&#8217;m going to run Linux as the primary OS on this machine.  I&#8217;ve heard good things about <a href="http://www.ubuntu.com/">Ubuntu</a> (in terms of being relatively easy to install and get going &#8212; I&#8217;ve reached an age where dicking about with system installers is no longer considered a productive use of my time).  I&#8217;m going to use the <a href="http://www.kubuntu.org/">Kubuntu</a> distribution, because, as I&#8217;ve mentioned previously, I <a href="http://jc.ngo.org.uk/blog/2006/07/10/day-1-of-60-tourist/">don&#8217;t get on with GNOME</a>, preferring KDE if I&#8217;ve got the choice.</p>
<p>On top of that Linux distribution I&#8217;m going to install the free VMWare Server.  And in to that I&#8217;m going to install FreeBSD, Solaris, and Windows distributions.  This will be something of a learning experience, as I last used Linux over a decade ago.  I imagine a few things have changed.  I&#8217;m also interested to see just how much of a performance hit VMWare imposes (especially with my gaming head on).</p>
<p>Hopefully this will make it easy for me to try out other things that have been happening in the FreeBSD space (like <a href="http://www.pcbsd.org/">PC-BSD</a>).</p>
<p>So I&#8217;m sat here writing away with a Kubuntu 6.10 CD prepared and ready to go.  I&#8217;m just going to boot for first time, see what happens, verify that everything comes up as it should, and then get on with the Kubuntu install.</p>
<p><b>13.58:</b>  Plug everything in and turn it on.  The fans make a God-awful noise when they start up, which subsides after 30 seconds or so.</p>
<p>The boot process seems stuck acquiring DHCP lease, which is odd, as everything else on this network has no problems with DHCP.  Network cable firmly plugged in to socket marked &#8220;0&#8243;, perhaps it should be in &#8220;1&#8243;.</p>
<p><b>14.04:</b> Possibly not DHCP, as the error messages that have now come up talk about PXE booting, and it shows &#8220;Operating System not found&#8221;.  Why is it PXE booting, instead of booting off the hard disk?  Solaris is supposed to be pre-installed.</p>
<p><b>14.06:</b> Try swapping the network cable to port 1 and reboot.  That has some effect &#8212; the boot now fails much faster, and displays the &#8220;Operating System not found&#8221; message again.  I wonder if the hard disk is not properly seated.</p>
<p><b>14.08:</b> Try swapping network cable back.  The side of the box has quick release catches, which means that opening it up, pulling out the hot-swappable disk, and reinserting it takes seconds.  Try rebooting again.</p>
<p><b>14.14:</b> Same PXE problems.  Time to reboot and check the BIOS.  This is interesting, the BIOS boot menu shows that the SATA drive is excluded from the boot order for some reason, with the PXE boot first on the list.  So I&#8217;ve shuffled that around and now the DVD is checked first, followed by the hard disk, with no PXE boot.  Saved and rebooted&#8230;</p>
<p><b>14.16:</b> That&#8217;s better.  The GRUB boot menu comes up, and Solaris starts.  &#8220;SunOS Release 5.10 Version Generic_118855-15 64-bit&#8221; according to the start up splash screen.  That&#8217;s enough of that, time to start with Kubuntu.</p>
<p><b>14.17:</b> I reboot with the Kubuntu CD in the drive.</p>
<p>That&#8217;s nice &#8212; I can select the keymap straight away.  Last time I did this with Solaris that setting wasn&#8217;t carried through to the final X configuration, I&#8217;m interested in seeing if it works with Kubuntu.  I choose the &#8220;United Kingdom&#8221; mapping.</p>
<p>I choose the &#8220;Install&#8221; option, and a progress dialog comes up.  The text is &#8220;Loading Linux Kernel&#8221;.  This rapidly gets to 95% and then halts.</p>
<p><b>14.25:</b> Been stuck at 95% for 7 minutes now.  That&#8217;s a bit excessive.  I&#8217;m going to reboot and try again.  It&#8217;s just possible that the CD is damaged in some way.  In which case I&#8217;ll try once more, and if it fails again, boot in to Solaris and burn the Kubuntu ISO image from there.</p>
<p><b>14.27:</b> Noted a &#8220;Check CD for defects&#8221; option on the Kubuntu boot menu, which is a nice touch.  I&#8217;m running that now.  There&#8217;s a very dark blue note at the bottom of the screen that this &#8220;may take some time&#8221;.</p>
<p><b>14.34:</b> Progress meter on the CD check is now at just over 75%.</p>
<p><b>14.36:</b> The check has now completed.  Took me a moment to realise, as the &#8220;Check has now completed, no defects found&#8221; message is displayed in that very dark blue text on a black background, which is not very legible.</p>
<p>This time around the kernel loads successfully.  CD grinds away for a bit.  Ah ha, a blue desktop with a mouse pointer has appeared, shortly followed by a list of items that are being ticked off one by one.  This looks a lot like a normal KDE startup to me, albeit in 800&#215;600.  I double click the installer application, and walk through the installation wizard.</p>
<p>Bonus points for carrying over my keyboard layout preferences.  £, &#8220;, and @ are all exactly where I expect to find them.</p>
<p>Disk partitioning is pretty simple.  At the moment I&#8217;m going for one big partition (with separate swap).</p>
<p><b>14.54:</b> I appear to be doomed to face progress meters that get stuck.  The &#8220;Creating ext3 file system for / in partition #1 of SCSI1&#8230;&#8221; progress bar hasn&#8217;t moved for the last 15 minutes, which is unnerving.  Is this expected with ext3?  I know that FreeBSD&#8217;s newfs() would complete on this in a matter of seconds.</p>
<p>What&#8217;s especially galling is that although I appear to be in KDE and the mouse moves, none of the menus are currently responding.  So I can&#8217;t, for example, fire up an xterm and do some digging in to exactly what&#8217;s going on at the moment.  I shall leave this for another five minutes and then if there&#8217;s no progress reboot and try again&#8230;</p>
<p><b>15.06:</b> Rebooted, and gone through the installation process again.  Looks as though the earlier install might not have hung, as the partition editor is now showing some of the disk as occupied.  I guess the lesson here <b>is</b> to leave it running.  So that&#8217;s what I&#8217;m going to do now.</p>
<p><b>15.20:</b> Progress dialog has now sprung in to life again.  Partitioning/formatting appears to have completed and files are now being installed.</p>
<p><b>15.40:</b> Everything appears to be installed, so, as prompted, I reboot.</p>
<p>The first problem is that the display is 1024&#215;768.  That&#8217;s all very well, but the LCD monitor is capable of 1600&#215;1200, so I&#8217;m peering at a very small display surrounded by lots of black pixels.  I&#8217;ve not had this problem with this monitor in X on FreeBSD before.</p>
<p>Adept has popped up and told me that there are 99 packages that need updating, so I&#8217;ve let it go off and update those.  While that&#8217;s happening I&#8217;m going to poke around and see what&#8217;s wrong with the screen.</p>
<p>KDE / Kubuntu / X doesn&#8217;t appear to have anything special for the graphics card and monitor.  The monitor, an Iiyama AU4831D isn&#8217;t listed in the monitor database, and had to go grovelling through <tt>/var/log/Xorg.0.log</tt> to determine that it was a Quadro FX 1500.</p>
<p>I&#8217;ll try and update to the newest Nvidia drivers and see if that has any effect&#8230;</p>
<p>&#8230; nope, nothing.</p>
<p>Ah ha.  Some judicious searching has turned up <a href="https://www.opensolaris.org/jive/thread.jspa?messageID=81153">this post on the OpenSolaris forums</a>.</p>
<p>To save you the trouble, or should it disappear, if you have an Iiyama AU4831D and you want to get the full resolution you need to add:</p>
<pre>&nbsp;&nbsp;&nbsp;&nbsp;Option &quot;ModeValidation&quot; &quot;NoDFPNativeResolutionCheck&quot;</pre>
<p>to <tt>/etc/X11/xorg.conf</tt>, otherwise the driver gets the wrong idea about the maximum resolution supported by the monitor.  Adding that and restarting the X server gets everything going in glorious 1600&#215;1200 again.</p>
<p>What with the updating, configuring KDE to behave the way I like, and futzing around trying to sort out the monitor it&#8217;s now 17.00 and I&#8217;ve got a few errands to run.  So that will probably be all I&#8217;ll have time to write today.  More updates tomorrow.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('105', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F28%2Fgetting-started-with-kubuntu%2F', 'Getting+started+with+Kubuntu'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_105">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/28/getting-started-with-kubuntu/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Subversion UK User Group / Google open source jam writeup</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/20/subversion-uk-user-group-google-open-source-jam-writeup/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/20/subversion-uk-user-group-google-open-source-jam-writeup/#comments</comments>
		<pubDate>Sat, 20 Jan 2007 14:32:48 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>plagger</category>

		<category>subversion</category>

		<category>googlecode</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/20/subversion-uk-user-group-google-open-source-jam-writeup/</guid>
		<description><![CDATA[Last Thursday (the 18th) I attended two open source events in London.  The first was the third Subversion UK User Group meeting, and the second was Google&#8217;s second Open Source Jam.

This was almost a disaster for me.  I was coming from docklands, and the DLR was suspended due to the storms that hit [...]]]></description>
			<content:encoded><![CDATA[<p>Last Thursday (the 18th) I attended two open source events in London.  The first was the third Subversion UK User Group meeting, and the second was Google&#8217;s second Open Source Jam.</p>
<p><a id="more-104"></a></p>
<p>This was almost a disaster for me.  I was coming from docklands, and the DLR was suspended due to the <a href="http://news.bbc.co.uk/1/hi/uk/6272193.stm?ls">storms that hit Europe</a>.  What should have been a 20 minute journey to Bank station turned in to a 50 minute nightmare.  I was due to give the first presentation, and had visions of causing problems for everyone else.  And visions of fainting.  Mental note &#8212; next time do not <a href="http://www.blood.co.uk/">give blood</a> 2 hours before delivering a talk.  Or perhaps, better not to deliver a presentation 2 hours after giving blood.</p>
<p>Anyway, I just made it in time.  The transport disruption caused by the weather meant that there weren&#8217;t as many people as the last get together (about 12 I think) but this also meant that it was also possible to have more inclusive discussions about points raised by the presentations.</p>
<p>I think mine went well.  There&#8217;s a PDF, slide-only version of &#8220;<a href="http://jc.ngo.org.uk/~nik/subversion-perl.pdf">Subversion and Perl, a tour through CPAN</a>&#8220;.  It ended up a tiny bit rushed &#8212; 24 slides in 25 minutes.  I should probably allow 90 seconds per slide for those sorts of slides next time. It&#8217;s a difficult balance to strike when writing them.  It&#8217;s all very well using the <a href="http://www.presentationzen.com/presentationzen/2005/09/living_large_ta.html">Takahashi Method</a> (big text, very few words, clkao did that to great effect at the previous meeting), but they&#8217;re not necessarily going to be very useful to the audience afterwards without extensive notes.</p>
<p><a href="http://www.dghda.com/blog/">Duane Griffin</a> commented to me that the information about <a href="http://search.cpan.org/dist/SVN-Notify/">SVN::Notify</a> had saved him some work, so I know at least one person found it useful :-)</p>
<p>The next presentation was from <a href="http://www.cmichaelpilato.com/">C. Michael Pilato</a>, going through some of what&#8217;s up-and-coming in Subversion over the next few minor releases (and 2.0). No real surprises for me there, since I follow the dev mailing list.  I was disappointed to discover that this was a conference call.  When I saw his name on the schedule I thought CollabNet might have flown him over to do some customer consulting.  I was looking forward to shaking his hand and saying &#8220;Thanks for the commit bit&#8221;.</p>
<p>Andrew Heald followed this with a &#8220;lessons learned&#8221; discussion / presentation about his experiences migrating a relatively large group of developers (around 80 or so) from CVS to Subversion for <a href="http://www.catlin.com/">Catlin</a>.  I hope the slides will be online soon.</p>
<p>The last presentation and demonstration was from Guido Haarmans, talking about the recently introduced <a href="http://open.collab.net/">Open CollabNet</a>.</p>
<p>I&#8217;ve had a poke around Open CollabNet previously, and I confess that I&#8217;m not quite getting &#8220;it&#8221;.  This might well be because it&#8217;s not aimed at me.  There&#8217;s a fair amount of content on there, and it includes a number of web based forums.  But I find that that just makes things harder to find &#8212; if you&#8217;re looking for Subversion info do you go to Open CollabNet or <a href="http://subversion.tigris.org/">subversion.tigris.org</a>?  And what do the web forums do that the users and dev mailing lists don&#8217;t?</p>
<p>And it doesn&#8217;t help that there are no updated feeds of the content available.  So it becomes yet another website that I have to remember to visit on a periodic basis (and I can&#8217;t roll it up in to <a href="http://planet-subversion.com/">Planet Subversion</a>).</p>
<p>On the flip-side, at work the next day I needed a site to point someone completely new to Subversion at, and they found Open CollabNet quite helpful.  So, as I say, I could very well just not be in the target audience.</p>
<p>And then it was on to the <a href="http://www.red-bean.com/ospowiki/LondonOpenSourceJam01">Google Open Source Jam</a>.</p>
<p>I travelled down with Duane Griffin and Dave Hodgkinson, who&#8217;d also been at the Subversion meeting.  During the journey Duane and I chatted about tools for extracting statistics from Subversion repositories.</p>
<p>The Google event was organised in to two main sections.  First, once we&#8217;d arrived, chatted a little bit, anyone that wanted to had the opportunity to give a lightning talk (5 or so minutes) about anything interesting that they were working on.  A few things caught my eye &#8212; mostly in the &#8220;That looks interesting&#8221; category, rather than the &#8220;I&#8217;ll be able to make a positive contribution to that project&#8221; category.  But I&#8217;ve got plenty of open source stuff on my plate at the moment, so that&#8217;s no bad thing.</p>
<p>Simon Stewart introduced <a href="http://code.google.com/p/webdriver/">WebDriver</a>, a tool to make it easy for developers to carry automated tests of webapps, even if they use Ajax and similar technologies.  Since it&#8217;s hosted at Google I was able show Simon the <a href="http://jc.ngo.org.uk:81/svnweb/webdriver/browse/trunk">SVN::Web front end to the WebDriver repo</a>, which he seemed impressed by.</p>
<p>Stathis Sideris showed us <a href="http://ditaa.sourceforge.net/">ditaa</a>.  This is very geeky &#8212; it takes ASCII art diagrams like this:</p>
<pre>&nbsp;&nbsp;&nbsp;&nbsp;+&#45;&#45;-&#45;&#45;&#45;--+&nbsp;&nbsp; +&#45;&#45;-&#45;&#45;&#45;-+&nbsp;&nbsp;&nbsp;&nbsp;+&#45;&#45;-&#45;&#45;&#45;-+
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| &#45;-+ ditaa +&#45;-&gt; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;Text&nbsp;&nbsp;|&nbsp;&nbsp; +&#45;&#45;-&#45;&#45;&#45;-+&nbsp;&nbsp;&nbsp;&nbsp;|diagram|
&nbsp;&nbsp;&nbsp;&nbsp;|Document|&nbsp;&nbsp; |!magic!|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp; {d}|&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
&nbsp;&nbsp;&nbsp;&nbsp;+&#45;&#45;-+&#45;&#45;&#45;-+&nbsp;&nbsp; +&#45;&#45;-&#45;&#45;&#45;-+&nbsp;&nbsp;&nbsp;&nbsp;+&#45;&#45;-&#45;&#45;&#45;-+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Lots of work&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-+</pre>
<p>and converts them to something like this;</p>
<p><img src="http://ditaa.sourceforge.net/images/first.png" alt="ditaa converted image" /></p>
<p>The other presentation that caught my eye was from Benoit Xhenseval, talking about, amongst other things, <a href="http://statsvn.org/">StatSVN</a>.  This is a Java application that gathers and reports on statistics about Subversion repositories.</p>
<p>As I mentioned earlier, I&#8217;d been talking about this sort of thing with Duane on the way over, and it&#8217;s this sort of serendipitous meeting that events like this help facilitate.</p>
<p>We talked about it some more.  After a bit of digging in to how it works I suggested they consider splitting the code in to two parts &#8212; a back end that is responsible for gathering and storing the data, and a front end that can query the data and generate reports (web based, e-mail, and so on).  That would make it possible to integrate it with a number of other tools.  Obviously, my interest is in bringing something like this SVN::Web.</p>
<p>Some other Perl mongers were in attendance and I took the opportunity to catch up with some of them.  Nick Clark detailed some issues he was having with P4 data export that make migration to Subversion difficult for Perl &#8212; if I understand correctly it&#8217;s about not being able to get at the P4 metadata that details which changesets have been integrated (which revisions have been merged, in Subversion parlance).</p>
<p>I was also able to jump in part way through an overheard conversation about scraping websites and sending to WAP devices.  I gave an impromptu intro to <a href="http://plagger.org/">Plagger</a> and the wealth of ways it might be able to help with this.</p>
<p>Next time I should remember to take a camera.  Stuart Yeates was snapping away, and has a <a href="http://www.flickr.com/photos/stuartyeates/sets/72157594489718820/">set of photos from the Google Open Source Jam event</a> on Flickr.</p>
<p>Thanks to the organisers, in particular Joe Walnes &#8212; providing space, projects, wireless, food, and drinks works well.  Maybe not conducive to actually getting patches committed there and then (perhaps that&#8217;s just me), due to eclectic nature of projects.  But it&#8217;s a great communication enabler.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('104', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F20%2Fsubversion-uk-user-group-google-open-source-jam-writeup%2F', 'Subversion+UK+User+Group+%2F+Google+open+source+jam+writeup'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_104">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/20/subversion-uk-user-group-google-open-source-jam-writeup/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Subversion commit access</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/18/subversion-commit-access/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/18/subversion-commit-access/#comments</comments>
		<pubDate>Thu, 18 Jan 2007 07:28:54 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>subversion</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/18/subversion-commit-access/</guid>
		<description><![CDATA[I&#8217;m very pleased to say that I&#8217;ve just been granted with a partial commit bit for the Subversion source code.  The developers have had enough of me popping up on the mailing list talking about issues with the Perl bindings and posting patches, and have given me the necessary access rights to fix and [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m very pleased to say that I&#8217;ve just been granted with a partial commit bit for the Subversion source code.  The developers have had enough of me popping up on the mailing list talking about issues with the Perl bindings and posting patches, and have given me the necessary access rights to fix and improve things myself.</p>
<p>As is traditional, my <a href="http://jc.ngo.org.uk/svnweb/subversion/revision?rev=23069">first commit</a> was to the list of Subversion committers.  This ensures that the ACLs are set up correctly and so on.</p>
<p>I&#8217;ll be working on the <a href="http://jc.ngo.org.uk/svnweb/subversion/browse/branches/perl-bindings-improvements">perl-bindings-improvements</a> branch, making sure that they&#8217;re up to date with respect to the rest of Subversion, and that they behave as &#8220;Perlishly&#8221; as possible for anyone else who needs to interoperate with Subversion repositories using Perl.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('103', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F18%2Fsubversion-commit-access%2F', 'Subversion+commit+access'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_103">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/18/subversion-commit-access/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Planet Subversion updates</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/17/planet-subversion-updates/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/17/planet-subversion-updates/#comments</comments>
		<pubDate>Wed, 17 Jan 2007 10:29:27 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>plagger</category>

		<category>subversion</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/17/planet-subversion-updates/</guid>
		<description><![CDATA[I&#8217;ve given Planet Subversion a facelift, and decided to splash the cash on a domain for it too &#8212; planet-subversion.com.  I&#8217;ve also recently added (but neglected to mention here) a feed from Mark Phippard, who has been writing some very interesting articles about the Subclipse project.

Share This
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve given <a href="http://planet-subversion.com/">Planet Subversion</a> a facelift, and decided to splash the cash on a domain for it too &#8212; <a href="http://planet-subversion.com/">planet-subversion.com</a>.  I&#8217;ve also recently added (but neglected to mention here) a feed from <a href="http://markphip.blogspot.com/index.html">Mark Phippard</a>, who has been writing some very interesting articles about the <a href="http://subclipse.tigris.org/">Subclipse</a> project.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('102', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F17%2Fplanet-subversion-updates%2F', 'Planet+Subversion+updates'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_102">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/17/planet-subversion-updates/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Perl parameter validation and error handling</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/15/perl-parameter-validation-and-error-handling/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/15/perl-parameter-validation-and-error-handling/#comments</comments>
		<pubDate>Mon, 15 Jan 2007 20:53:48 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/15/perl-parameter-validation-and-error-handling/</guid>
		<description><![CDATA[I write and maintain quite a lot of Perl software.  Much of it is open source and available on CPAN.  Most of it consists of libraries designed to be used by other applications, rather than applications in their own right.
One of Perl&#8217;s strengths is that &#8220;There&#8217;s more than one way to do it&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>I write and maintain quite a lot of Perl software.  Much of it is open source and <a href="http://search.cpan.org/~nikc/">available on CPAN</a>.  Most of it consists of libraries designed to be used by other applications, rather than applications in their own right.</p>
<p>One of Perl&#8217;s strengths is that &#8220;There&#8217;s more than one way to do it&#8221; (TMTOWTDI, often pronounced <i>tim-toady</i>).  This makes for a language that is flexible, and allows you to write a solution to a problem that matches the problem, rather than trying to shoehorn the problem in to the language in order to solve it.</p>
<p>This is also one of Perl&#8217;s weaknesses.  There can be many ways to solve a particular problem &#8212; some of them are not optimal.</p>
<p><a id="more-101"></a></p>
<p>One of those, that I&#8217;ve rolled countless home-grown solutions for over the years, is that of parameter validation and handling.  When writing code (especially library code that&#8217;s probably going to be called by code other than your own) it pays to be defensive.  Catch and report errors as soon as possible and you can save yourself (and quite possibly someone else) a boatload of debugging time.</p>
<p>Perl&#8217;s parameter passing is very flexible, adhering to the TMTOWTDI principle.  Which also means there are lots of ways to carry out parameter validation.  Here&#8217;s the approach that I&#8217;ve settled on.  I hope you find it useful too.</p>
<p>I&#8217;m lazy.  I want to hand as much of the work off to someone else&#8217;s code as possible.  To that end I make use of two other Perl modules.  <a href="http://search.cpan.org/~drolsky/Params-Validate/">Params::Validate</a> and <a href="http://search.cpan.org/~drolsky/Exception-Class/">Exception::Class</a>.  Together, these two can do all the heavy lifting of detecting errors in the parameter list and reporting them in a coherent manner to the caller.</p>
<p>Consider a hypothetical module, called <tt>Example::Module</tt>.  This module provides one function, which accepts a hashref, the keys of which specify parameter names, the values of which are the parameter values.</p>
<p>Here&#8217;s how I&#8217;d start that module.</p>
<pre>&nbsp;&nbsp;1 package Example::Module
&nbsp;&nbsp;2
&nbsp;&nbsp;3 use strict;
&nbsp;&nbsp;4 use warnings
&nbsp;&nbsp;5 
&nbsp;&nbsp;6 use Params::Validate qw(:all);
&nbsp;&nbsp;7 use Exception::Class(
&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp; &#039;Example::Module::X::Args&#039;
&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; { alias =&gt; &#039;throw_args&#039;, },
 10 );
 11
 12 Params::Validate::validation_options(
 13&nbsp;&nbsp;&nbsp;&nbsp; on_fail =&gt; sub { throw_args(error =&gt; shift) },
 14 );</pre>
<p>The first four lines declare the module and enable&#8217;s Perl&#8217;s strictness checks and related warnings.  These are more or less boilerplate, and should be a standard part of any code written in Perl (with, perhaps, the exception of one liners written on the command line).</p>
<p>Line 6 loads <tt>Params::Validate</tt>, and imports the functions and constants that it defines in to the caller&#8217;s (<tt>Example::Module</tt>) namespace.</p>
<p>Lines 7 through 10 are more interesting, doing a number of things.</p>
<p>The Exception::Class module is loaded.  It&#8217;s <tt>import()</tt> routine is called, and told to create a new package, <tt>Example::Module::X::Args</tt>.  I use this convention frequently now &#8212; exceptions are created in namespaces based on the main namespace, with an appended &#8220;::X&#8221;, followed by the type of exception.  In this case these exceptions relate to problems with the arguments passed to functions.  The <tt>alias</tt> directive creates a new function, called <tt>throw_args()</tt>.  If called, this function will throw an exception of the type <tt>Example::Module::X::Args</tt>, passing along any parameters it&#8217;s given.</p>
<p>Lines 12 through 13 make use of this.  Now that <tt>throw_args()</tt> has been created, <tt>Params::Validate::validation_options()</tt> is called.  This provides an interface in to the inner workings of <tt>Params::Validate</tt>.  This stanza configures <tt>Params::Validate</tt> to call the newly created <tt>throw_args()</tt> function is parameter validation fails.  The <tt>error => shift</tt> code ensures that any error message created by Params::Validate is included in the exception.</p>
<p>That&#8217;s all that you need to do in terms of set up.  Now you just need to make sure that any function that requires parameter validation uses the Params::Validate functions appropriately.</p>
<p>Suppose we have one function in this module, <tt>frob()</tt>, that takes a hash ref of arguments:</p>
<pre>&nbsp;&nbsp;1 sub frob {
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; my $args = validate(@_, {
&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foo = 1,
&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp; return 1;
&nbsp;&nbsp;7 }</pre>
<p>That&#8217;s enough to declare that <tt>foo</tt> is mandatory parameter.  Now if you try and call that function without passing in that parameter your application dies with an appropriate message.</p>
<pre>Example::Module::frob();
&nbsp;
# Dies, printing &quot;Mandatory parameter &#039;foo&#039; missing in call to Example::Module::frob&quot;
&nbsp;
Example::Module::frob(foo =&gt; 1); # works</pre>
<p><tt>Exception::Class</tt> has other tricks up its sleeve.  For example, instead of dying with a single error message you can have it generate a stack trace any time an exception is raised.  By inserting this line before the call to <tt>validation_options</tt>:</p>
<pre>Example::Module::X::Args-&gt;Trace(1)</pre>
<p>this tracing facility is enabled.</p>
<p><tt>Exception::Class</tt> can be used to easily throw other errors as well &#8212; errors that it might make more sense to trap.  Consider an application that retrieves and processes data from a database.  Your <tt>Exception::Class</tt> import might look like this:</p>
<pre>use Exception::Class(
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::Args&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_args&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db&#039;, },
);</pre>
<p>Now, if your library needs to indicate that a database error has occured it can:</p>
<pre>throw_db(&quot;Text of the error message&quot;);</pre>
<p>and these errors will be distinguishable from errors due to incorrect arguments.  More importantly, these errors are distinguished by the class in which they are defined, rather than the text of the error message &#8212; distinguishing errors programmatically by the text of error messages is fragile, and prone to problems when messages are changed, either because the text has been reworded, or it has been translated.</p>
<p>You can take this further and produce class hierarchies of exceptions as necessary.</p>
<pre>use Exception::Class(
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::Args&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_args&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB::Connect&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db_connect&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB::Prepare&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db_prepare&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB::Query&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db_query&#039;, },
);</pre>
<p>This allows for distinguation of exceptions caused by argument parsing, database connections, query preparation, and query execution.</p>
<p><b>Edited to add:</b></p>
<p>You would do that like so:</p>
<pre># Use the &#039;isa&#039; option to explicitly specify a class hierarchy
use Exception::Class(
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::Args&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_args&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB::Connect&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db_connect&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isa&nbsp;&nbsp; =&gt; &#039;Example::Module::X::DB&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB::Prepare&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db_prepare&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isa&nbsp;&nbsp; =&gt; &#039;Example::Module::X::DB&#039;, },
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::DB::Query&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_db_query&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isa&nbsp;&nbsp; =&gt; &#039;Example::Module::X::DB&#039;, },
);
&nbsp;
# Carry out some work.&nbsp;&nbsp;Trap any exceptions, and handle them
# at the end
eval {
&nbsp;&nbsp;&nbsp;&nbsp;my $db = connect_to_db();&nbsp;&nbsp; # might throw ::X::DB::Connect
&nbsp;&nbsp;&nbsp;&nbsp;my $sql = get_sql_from_phrasebook(); # might call die()
&nbsp;&nbsp;&nbsp;&nbsp;my $q = prepare_query($db); # might throw ::X::DB::Prepare
&nbsp;&nbsp;&nbsp;&nbsp;my @results = query_db($q); # might throw ::X::DB::Query
&nbsp;&nbsp;&nbsp;&nbsp;do_something_with(@results);
}
&nbsp;
# Handle any exceptions.&nbsp;&nbsp;If a ::DB::Query exception occurs then
# print one set of diagnostics.&nbsp;&nbsp;If any other ::DB exception occurs
# print another set of diagnostics.&nbsp;&nbsp;If any other exception occurs
# (e.g., ::Args, or the code died for some other reason) this is a
# &quot;can&#039;t happen&quot; situation, and the best thing to do is to die here
# with debugging information.
my $e;
if($e = Example::Module::X::DB::Query-&gt;caught()) {
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;There was an error querying the database\n&quot;;
} elsif($e = Exception::Class::X::DB-&gt;caught()) {
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;There was an error working with the database\n&quot;;
} elsif($e = Exception::Class-&gt;caught()) {
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Something unexpected failed.&nbsp;&nbsp;The error was:\n&quot;;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;# rethrow the error
&nbsp;&nbsp;&nbsp;&nbsp;ref $e ? $e-&gt;rethrow() : die $e;
}</pre>
<p>This has hoisted the error checking code out of the way of the code that does the actual work (which is in the <tt>eval</tt> block).  This makes the functionality of this code clearer and easier to understand.  The error handling logic is also in one place &#8212; so if this sort of error handling is common throughout the application it can be abstracted away in to a separate function.</p>
<p><b>End of edits</b></p>
<p>Not every application is going to need this sort of exception hierarchy (<a href="http://search.cpan.org/~nikc/SVN-Web/">SVN::Web</a>, for example, has a single exception type, because any error basically means do the same thing; prepare an error message and show it to the user), but it&#8217;s nice to know it&#8217;s there.</p>
<p>Here&#8217;s an example that you can cut/paste and play around with.  It shows a second function, <tt>frob2()</tt>, which uses a few more of the <tt>Params::Validate</tt> features.  It also has various commented lines, which you can uncomment as necessary, to experiment with the effects of the parameter validation and the exceptions that are thrown.</p>
<pre>#!/usr/bin/perl
&nbsp;
use strict;
use warnings;
&nbsp;
package Example::Module;
&nbsp;
use strict;
use warnings;
&nbsp;
use Params::Validate qw(:all);
use Exception::Class(
&nbsp;&nbsp;&nbsp;&nbsp;&#039;Example::Module::X::Args&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; { alias =&gt; &#039;throw_args&#039;, },
);
&nbsp;
# Change this to -&gt;Trace(1) to enable stack traces for argument errors
Example::Module::X::Args-&gt;Trace(0);
&nbsp;
Params::Validate::validation_options(
&nbsp;&nbsp;&nbsp;&nbsp;on_fail =&gt; sub { throw_args(error =&gt; shift) }
);
&nbsp;&nbsp;&nbsp;&nbsp;
# Show basic parameter validation and exception throwing.&nbsp;&nbsp;The &#039;foo&#039;
# key is mandatory, all other keys are forbidden.
sub frob {
&nbsp;&nbsp;&nbsp;&nbsp;my $args = validate(@_, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo =&gt; 1,
&nbsp;&nbsp;&nbsp;&nbsp;});
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return $args-&gt;{foo};
}
&nbsp;
sub frob2 {
&nbsp;&nbsp;&nbsp;&nbsp;my $args = validate(@_, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo =&gt; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type =&gt; SCALAR,&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default =&gt; &#039;The default&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;});

&nbsp;&nbsp;&nbsp;&nbsp;return $args-&gt;{foo};
}

package main;

# Uncomment to see missed parameter handling
#print Example::Module::frob(), &quot;\n&quot;;

# Uncomment to see extra parameter handling
#print Example::Module::frob(for =&gt; 1, bar =&gt; 1), &quot;\n&quot;;
&nbsp;
# Uncomment to see what happens when the params are correct
#print Example::Module::frob({foo =&gt; &#039;bar&#039;}), &quot;\n&quot;;
&nbsp;
# Uncomment to see parameters with defaults
#print Example::Module::frob2(), &quot;\n&quot;;
#print Example::Module::frob2({foo =&gt; &#039;bar&#039;}), &quot;\n&quot;;
&nbsp;
# Here&#039;s an example of exception handling.&nbsp;&nbsp;This section will never
# run if any of the previous calls (esp. to frob()) failed, because
# they were not wrapped in eval { }, and will have caused the program
# to abort.&nbsp;&nbsp;This error will not cause the program to abort, because
# it&#039;s wrapped in eval { }.
my $e;
eval {
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Just before eval&#039;d call to frob()\n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;# Uncomment the next line to see how other errors are handled
&nbsp;&nbsp;&nbsp;&nbsp;#die &quot;This is not an argument error\n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;print Example::Module::frob(), &quot;\n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Just after eval&#039;d call to frob()\n&quot;; # won&#039;t print
};
&nbsp;
if($e = Example::Module::X::Args-&gt;caught()) {
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;An argument error occured, but we&#039;re continuing\n&quot;;
} elsif($e = Exception::Class-&gt;caught()) {
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Something unexpected failed.&nbsp;&nbsp;The error was:\n&quot;;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;# rethrow the error
&nbsp;&nbsp;&nbsp;&nbsp;ref $e ? $e-&gt;rethrow() : die $e;
}
&nbsp;
print &quot;Made it to the end\n&quot;;</pre>
<p class="akst_link"><a href="javascript:void(akst_share('101', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F15%2Fperl-parameter-validation-and-error-handling%2F', 'Perl+parameter+validation+and+error+handling'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_101">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/15/perl-parameter-validation-and-error-handling/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Open Source support and OpenLogic</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/13/open-source-support-and-openlogic/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/13/open-source-support-and-openlogic/#comments</comments>
		<pubDate>Sat, 13 Jan 2007 21:28:28 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/13/open-source-support-and-openlogic/</guid>
		<description><![CDATA[One of the common pieces of FUD used to argue against the use of open source software is &#8220;There&#8217;s no vendor support.  If it breaks, who do we turn to?&#8221;.
There are a number of answers to this particular concern.

First, there&#8217;s the community of developers that develop the software, and the wider community of other [...]]]></description>
			<content:encoded><![CDATA[<p>One of the common pieces of FUD used to argue against the use of open source software is &#8220;There&#8217;s no vendor support.  If it breaks, who do we turn to?&#8221;.</p>
<p>There are a number of answers to this particular concern.</p>
<p><a id="more-97"></a></p>
<p>First, there&#8217;s the community of developers that develop the software, and the wider community of other users.  It&#8217;s something of a cliche, but I&#8217;ve always received better support from a user group mailing list than I&#8217;ve ever received from a commercial vendor.  In fact, one of the first questions I ask of any vendor I have to deal with is &#8220;How can I send a message to/ask a question of your other customers?&#8221;</p>
<p>Second, if you&#8217;re large enough, you do the support in-house.  This is part of my role at $dayjob, where the open source version of Sendmail is used extensively.  If it breaks, or we need a feature adding, or a bug fixing, it&#8217;s down to me (and my team) to do it.  We might then talk to the community (and feed our changes back, see the <a href=")http://www.sendmail.org/releases/8.14.0.Beta4.php">release notes for 8.14.0b4</a> for example) but internally we&#8217;re the support group.  Recipients of this message are not always comfortable hearing it, but so far I&#8217;ve been successful in hammering away at this point.</p>
<p>Third, you can choose to pay for third party support.  There are a number of organisations that do (or did) this.  In some cases it&#8217;s a large part of their reason for being &#8212; for example, much of RedHat&#8217;s success came from being a vendor that large organisations (who didn&#8217;t or couldn&#8217;t take point 2 on board) could sign a support deal with.  Then there&#8217;s companies like <a href="http://www.collab.net/">CollabNet</a>, who provide (amongst other things) commercial support for Subversion, or <a href="http://www.sendmail.com/">Sendmail Inc.</a> who do the same for Sendmail.  All of these organisations can (and in many cases have) also build on the open source software and provide their own proprietry benefits, tools, applications, documentation, and so on.</p>
<p><a href="http://www.openlogic.com/">OpenLogic</a> are another organisation providing third party support, training, and consulting, but with something of a twist.  They have actively engaged with (some of) the open source community, and formed what they call the &#8220;OpenLogic Expert Community&#8221;.  As their site <a href="http://www.openlogic.com/community/index.php">says</a>:</p>
<blockquote><p>OpenLogic and the OpenLogic Expert Community bridge that gap by providing a single avenue for obtaining expert support on over 200 open source projects. OpenLogic&#8217;s internal technical support team acts as the frontline of support, answering customer questions and investigating incidents. For more complex issues, OpenLogic turns to the OpenLogic Expert Community. These open source experts work in partnership with OpenLogic to troubleshoot and resolve customer problems. Through the Expert Community, OpenLogic is connecting enterprises users with committed, passionate and expert developers dedicated to the success of open source.</p></blockquote>
<p>This piqued my interest at the beginning of 2006, and I signed up as a member to help out.  I&#8217;ve been a bit busy since then, and haven&#8217;t had an opportunity to do much, but I was fortunate enough that over the Christmas period some queries came in that were in my areas of expertise.</p>
<p>The result&#8217;s a deposit in to my Paypal account, and a shiny Xbox 360 on its way to me.</p>
<p>As a bonus, there&#8217;s a regularly updated, informative (and informed) <a href="http://www.openlogic.com/blogs/">OpenLogic blog</a>.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('97', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F13%2Fopen-source-support-and-openlogic%2F', 'Open+Source+support+and+OpenLogic'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_97">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/13/open-source-support-and-openlogic/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SVN::Web 0.50 released</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/12/svnweb-050-released/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/12/svnweb-050-released/#comments</comments>
		<pubDate>Fri, 12 Jan 2007 17:17:18 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>svn-web</category>

		<category>subversion</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/12/svnweb-050-released/</guid>
		<description><![CDATA[After a slightly longer development process than I would have liked (I had several hard disks choose inopportune moments to go south &#8212; no data loss thanks to backups, but I took the opportunity to shuffle some hardware around), SVN::Web 0.50 has been released, and should now be available on CPAN.
There are quite a few [...]]]></description>
			<content:encoded><![CDATA[<p>After a slightly longer development process than I would have liked (I had several hard disks choose inopportune moments to go south &#8212; no data loss thanks to backups, but I took the opportunity to shuffle some hardware around), SVN::Web 0.50 has been released, and should now be available on <a href="http://search.cpan.org/~nikc/SVN-Web/">CPAN</a>.</p>
<p>There are quite a few significant changes in this version&#8230;</p>
<p><a id="more-100"></a></p>
<p>Chief amongst them is that SVN::Web now supports accessing remote repositories.  Your SVN::Web instance no longer needs to access the same filesystem as the repository.  This makes various <a href="http://jc.ngo.org.uk/blog/2006/11/29/svnweb-and-google-code-hosting/">interesting tricks</a> possible too.</p>
<p>This entailed switching to use the SVN::Client API when accessing repositories.  This made it possible to support &#8220;<a href="http://jc.ngo.org.uk/svnweb/jc/blame/nik/CPAN/SVN-Web/trunk/Build.PL">svn blame</a>&#8221; style functionality, which is another feature that people have been asking for.</p>
<p>The mechanism for passing log messages through various filters (e.g., to turn e-mail addresses in the message in to hyperlinks) has also changed, to be more general, and support different filters for different repositories.</p>
<p>The <a href="http://search.cpan.org/~nikc/SVN-Web/CHANGES.pod">complete changelist</a> is available, as are the <a href="http://search.cpan.org/~nikc/SVN-Web/UPDATING.pod">updating instructions</a> for migrating to the new version.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('100', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F12%2Fsvnweb-050-released%2F', 'SVN%3A%3AWeb+0.50+released'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_100">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/12/svnweb-050-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Subversion UK User Group / Google Open Source Jam, 18th January 2007</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/12/subversion-uk-user-group-google-open-source-jam-18th-january-2007/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/12/subversion-uk-user-group-google-open-source-jam-18th-january-2007/#comments</comments>
		<pubDate>Fri, 12 Jan 2007 09:43:56 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>subversion</category>

		<category>googlecode</category>

		<category>open source</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/12/subversion-uk-user-group-google-open-source-jam-18th-january-2007/</guid>
		<description><![CDATA[If you&#8217;re in London on Thursday 18th January and you&#8217;ve got an interest in Subversion then you might want to come along to the next Subversion UK User Group meeting.  It&#8217;s at 3pm, there are directions and sign up instructions at that link.
I&#8217;ll be there, giving a tour of the Subversion related applications and [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re in London on Thursday 18th January and you&#8217;ve got an interest in Subversion then you might want to come along to the <a href="http://www.clearvision-cm.com/cms/site/news/subversion_user_group_uk_next_meeting_18th_january_2007.aspx">next Subversion UK User Group meeting</a>.  It&#8217;s at 3pm, there are directions and sign up instructions at that link.</p>
<p>I&#8217;ll be there, giving a tour of the Subversion related applications and tools that are available in the Perl space.</p>
<p>And after that it&#8217;s the first <a href="http://www.red-bean.com/ospowiki/LondonOpenSourceJam01">London Google Open Source Jam of 2007</a> &#8212; an opportunity to catch up with other open source developers, and find out more about interesting projects that people are working on.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('99', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F12%2Fsubversion-uk-user-group-google-open-source-jam-18th-january-2007%2F', 'Subversion+UK+User+Group+%2F+Google+Open+Source+Jam%2C+18th+January+2007'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_99">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/12/subversion-uk-user-group-google-open-source-jam-18th-january-2007/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Alerting users that their PCs are compromised</title>
		<link>http://jc.ngo.org.uk/blog/2007/01/09/alerting-users-that-their-pcs-are-compromised/</link>
		<comments>http://jc.ngo.org.uk/blog/2007/01/09/alerting-users-that-their-pcs-are-compromised/#comments</comments>
		<pubDate>Tue, 09 Jan 2007 15:34:01 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>spam</category>

		<category>phishing</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2007/01/09/alerting-users-that-their-pcs-are-compromised/</guid>
		<description><![CDATA[A great deal of spam is sent by &#8220;botnets&#8220;.  These are (typically) Windows PCs that have been compromised in some manner, and are now illicitly controlled by a third party.  This third party uses the network of thousands of PCs that they have compromised to:

Send spam
Host phishing sites
Carry out denial of service attacks

There [...]]]></description>
			<content:encoded><![CDATA[<p>A great deal of spam is sent by &#8220;<a href="http://en.wikipedia.org/wiki/Botnet">botnets</a>&#8220;.  These are (typically) Windows PCs that have been compromised in some manner, and are now illicitly controlled by a third party.  This third party uses the network of thousands of PCs that they have compromised to:</p>
<ol>
<li>Send spam</li>
<li>Host phishing sites</li>
<li>Carry out denial of service attacks</li>
</ol>
<p>There are many DNS based Black Lists (<a href="http://en.wikipedia.org/wiki/DNSBL">DNSBLs</a>) operated by numerous groups that aim to list the IP addresses of systems that have been compromised in this way.  This allows mail server operators to configure their systems to query these DNSBLs and reject messages that are being sent from a compromised system.</p>
<p>The problem with this approach is that it&#8217;s not visible to the owner of the compromised system.  They might notice that it&#8217;s behaving a little slower, or that their network connection doesn&#8217;t seem as fast as it was, but they&#8217;re not going to know why, because there&#8217;s no easy mechanism to alert them.</p>
<p>In a perfect world, Internet Service Providers would monitor these DNSBLs, notice when IP addresses of their customers appear on them, and terminate (or provide limited) service to that customer, along with appropriate assistance to help them clean their system.</p>
<p>In practice this rarely happens.</p>
<p>It occured to me that one way to make the fact that their PC has been compromised more visible to end users would be by enlisting the help of companies that host or provide online game environments.</p>
<p>For example, consider <a href="http://www.secondlife.com/">Second Life</a>, <a href="http://www.eve-online.com/">Eve</a>, or <a href="http://www.worldofwarcraft.com/">World of Warcraft</a>.  All huge, multi-player games/environments, to which millions of people connect every day.</p>
<p>If the companies that host these environments were to check the IP addresses of connecting systems against these DNSBLs, they could provide a warning to the player that it&#8217;s highly likely that their PC has been compromised, and that they should make sure their anti-virus is up to date, and so on.</p>
<p>Further, suppose you&#8217;ve got a PC and an <a href="http://www.xbox.com/">XBox</a> or Nintendo <a href="http://www.wii.com/">Wii</a> at home<sup>1</sup>.  Both of those game systems support online play.  And through a networking quirk that I don&#8217;t need to go in to here (NAT), it&#8217;s highly likely that the PC and the games console(s) are going to appear online with the same IP address.</p>
<p>So if the PC appears on a DNSBL the Wii or XBox is going to appear on that DNSBL too.  This provides an opportunity for Microsoft and Nintendo to check the IP address, and again, place a warning in the &#8220;dashboard&#8221; (<a href="thttp://en.wikipedia.org/wiki/Xbox_360#Dashboard">XBox dashboard</a>, <a href="http://en.wikipedia.org/wiki/Nintendo_Wi-Fi_Connection">Nintendo Wi-Fi Connection</a>) that their systems display to the user as they go online.</p>
<p>This could significantly raise the awareness of owners/operators of compromised PCs.</p>
<p><small><sup>1</sup> Guess what I got for Christmas :-)</small>
</p>
<p class="akst_link"><a href="javascript:void(akst_share('98', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2007%2F01%2F09%2Falerting-users-that-their-pcs-are-compromised%2F', 'Alerting+users+that+their+PCs+are+compromised'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_98">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2007/01/09/alerting-users-that-their-pcs-are-compromised/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Identity theft</title>
		<link>http://jc.ngo.org.uk/blog/2006/12/14/identity-theft/</link>
		<comments>http://jc.ngo.org.uk/blog/2006/12/14/identity-theft/#comments</comments>
		<pubDate>Thu, 14 Dec 2006 21:35:03 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>spam</category>

		<category>guardian</category>

		<category>phishing</category>

		<category>identitytheft</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2006/12/14/identify-theft/</guid>
		<description><![CDATA[I&#8217;ve just discovered that I&#8217;ve been an unwitting participant in an identity theft.
But not, perhaps, in the way that you might imagine.

As already chronicled, some of my writing recently made it in to The Guardian.  As is the way of these things The Guardian like to pay their writers, so I sent off my [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just discovered that I&#8217;ve been an unwitting participant in an identity theft.</p>
<p>But not, perhaps, in the way that you might imagine.</p>
<p><a id="more-96"></a></p>
<p>As already chronicled, <a href="http://technology.guardian.co.uk/online/insideit/story/0,,1954392,00.html">some of my writing</a> recently made it in to <a href="http://www.guardian.co.uk/">The Guardian</a>.  As is the way of these things The Guardian like to pay their writers, so I sent off my details to their billing department and waited for the money to come rolling in (as you do).</p>
<p>It turns out that, by an odd coincidence, I&#8217;m not the only Nik Clayton to write for The Guardian.  I&#8217;m not even the first.  This other <a href="http://www.nickclayton.com/">Nick Clayton</a> (note the extra &#8220;c&#8221;) has written a number of columns for them, and they&#8217;re also about technology matters.</p>
<p>This much became apparent when I received an e-mail from The Guardian&#8217;s billing department today confirming that they had dispatched payment for two articles that Nick had written to me.  This e-mail contained Nick&#8217;s name and address details, and the payment details (amounts) for the articles he&#8217;s written.  But it also contains my bank details (account number and sort code).  The money hasn&#8217;t been deposited in to my account yet, but I imagine it soon will be.</p>
<p>A bit of Googling turned up Nick&#8217;s site, and a bit more Googling turned up a phone number, so I&#8217;ve called him, and had the slightly surreal experience of:</p>
<blockquote><p>Good evening.  Could I speak to Nick Clayton?</p></blockquote>
<blockquote><p>Speaking</p></blockquote>
<blockquote><p>Hi.  It&#8217;s Nik Clayton here&#8230;</p></blockquote>
<p>Now I know how <a href="http://www.davegorman.com/search.htm">Dave Gorman</a> must feel.</p>
<p>I&#8217;ve tried calling The Guardian&#8217;s billing department but the number given in the e-mail redirects to voice mail at the moment, so I&#8217;ll be in touch with them again tomorrow morning.</p>
<p>There are at least four risks here.</p>
<p>First, The Guardian&#8217;s billing department will apparently change the sort code, bank account, and e-mail address details that they hold for writers on the basis of a single unauthenticated e-mail.  My message to them was:</p>
<blockquote><p>Charles Arthur asked me to send my payment details for</p>
<p>http://technology.guardian.co.uk/online/insideit/story/0,,1954392,00.html</p>
<p>to you.</p>
<p>Sort code is XX XX XX, the account number is XXXXXXXX.</p>
<p>Please let me know if there are any problems.</p></blockquote>
<p>Second, when they pay their writers they send out an e-mail that contains, in clear, the writer&#8217;s name, reference number, full address, sort code, bank account number, and the values of the payments.  This may well be enough to carry out a social engineering attack.</p>
<p>Third, this could easily have gone the other way, and my bank account details could have been forwarded to Nick Clayton.  Had he been nefarious I imagine that (given that we share the same name) these could have been used to carry out a very effective identity theft.</p>
<p>Fourth, had I not been quite so honest I could probably have got away with this for some time &#8212; at the very least, continuing to earn interest on the money that The Guardian have paid.</p>
<p>Hmm.  I wonder if The Guardian would like to use this as the basis for an article&#8230;
</p>
<p class="akst_link"><a href="javascript:void(akst_share('96', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2006%2F12%2F14%2Fidentity-theft%2F', 'Identity+theft'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_96">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2006/12/14/identity-theft/feed/</wfw:commentRss>
		</item>
		<item>
		<title>use.perl journals and full text feeds</title>
		<link>http://jc.ngo.org.uk/blog/2006/12/05/useperl-journals-and-full-text-feeds/</link>
		<comments>http://jc.ngo.org.uk/blog/2006/12/05/useperl-journals-and-full-text-feeds/#comments</comments>
		<pubDate>Tue, 05 Dec 2006 21:16:58 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>plagger</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2006/12/05/useperl-journals-and-full-text-feeds/</guid>
		<description><![CDATA[One of the sites I make a point of reading regularly is use.perl, and in particular, the user journals / blogs.  They don&#8217;t take too long to read, and there&#8217;s normally a couple of posts a day that teach me something I didn&#8217;t know about Perl, or that highlight a new module that&#8217;s doing [...]]]></description>
			<content:encoded><![CDATA[<p>One of the sites I make a point of reading regularly is <a href="http://use.perl.org/">use.perl</a>, and in particular, the user <a href="http://use.perl.org/search.pl?op=journals">journals / blogs</a>.  They don&#8217;t take too long to read, and there&#8217;s normally a couple of posts a day that teach me something I didn&#8217;t know about Perl, or that highlight a new module that&#8217;s doing something useful.</p>
<p>But there&#8217;s a problem.</p>
<p><a id="more-93"></a></p>
<p>The feeds for the use.perl journals don&#8217;t include the full text of the entry.  This is a pain &#8212; most entries aren&#8217;t too long, and I&#8217;d much rather read them all in my aggregator of choice, rather than have to click on lots of different links to see each entry in full.</p>
<p><a href="http://www.plagger.org/">Plagger</a> to the rescue.  It can extract the links from the <a href="http://use.perl.org/search.pl?op=journals">list of new journals</a>, follow the links to find the individual journal entries, and then extract the content from those pages to build a new feed that contains the full text of the entries.</p>
<p>To do this with Plagger requires two config files.</p>
<p>First, <tt>config.yaml</tt>.  You can put this anywhere you like.</p>
<pre>plugins:
&nbsp;&nbsp;- module: Subscription::Config
&nbsp;&nbsp;&nbsp;&nbsp;config:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;feed:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- url: http://use.perl.org/search.pl?op=journals
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;meta:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;follow_link: /journal/\d+
&nbsp;&nbsp;- module: CustomFeed::Simple
&nbsp;&nbsp;- module: Publish::Feed
&nbsp;&nbsp;&nbsp;&nbsp;config:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir: /home/nik/public_html/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;format: RSS
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filename: use.perl.journals.rss
&nbsp;&nbsp;- module: Filter::EntryFullText</pre>
<p>This instructs Plagger to build a feed by starting at the journal page and following every link that matches the regexp <tt>/journal/\d+</tt>.  This feed is published at <tt>use.perl.journals.rss</tt>, and takes a trip through <tt>Plagger::Plugin::Filter::EntryFullText</tt> to extract the content for each entry.</p>
<p>Now you need a config file for <tt>Plagger::Plugin::Filter::EntryFullText</tt>.  This needs to be in the correct sub-directory of your Plagger assets path.  On my system that&#8217;s <tt>/usr/local/share/Plagger/assets/plugins/Filter-EntryFullText</tt>.  If you take a look in that directory (or its equivalent on your system) you&#8217;ll see tens of small configuration files.</p>
<p>There&#8217;s one configuration file for every site that <tt>Filter::EntryFullText</tt> knows about.</p>
<p>I created a new file in this directory called <tt>use.perl.journal.yaml</tt>, with the following contents.</p>
<pre>handle: use\.perl\.org/.*?/journal/\d+
extract_xpath:
&nbsp;&nbsp;title: //div[@id=&quot;journalslashdot&quot;]/div[@class=&quot;title&quot;]/h3/text()
&nbsp;&nbsp;body: //div[@class=&quot;intro&quot;]
&nbsp;&nbsp;author: /html/head/link[@rel=&quot;author&quot;]/@title
&nbsp;&nbsp;day: //div[@id=&quot;journalslashdot&quot;]/div[@class=&quot;journaldate&quot;]/text()
&nbsp;&nbsp;time: //div[@id=&quot;journalslashdot&quot;]/div[@class=&quot;details&quot;]/text()
extract_after_hook: |
&nbsp;&nbsp;my %months = (January&nbsp;&nbsp;=&gt; 1,&nbsp;&nbsp;February =&gt; 2,&nbsp;&nbsp;March&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 3, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;April&nbsp;&nbsp;&nbsp;&nbsp;=&gt; 4,&nbsp;&nbsp;May&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; 5,&nbsp;&nbsp;June&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; 6, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;July&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 7,&nbsp;&nbsp;August&nbsp;&nbsp; =&gt; 8,&nbsp;&nbsp;September =&gt; 9, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;October&nbsp;&nbsp;=&gt; 10, November =&gt; 11, December&nbsp;&nbsp;=&gt; 12);
&nbsp;&nbsp;my($m, $d, $y) = $data-&gt;{day} =~ /([a-z]+)\s+(\d+),s(\d{4})/i;
&nbsp;&nbsp;$m = $months{$m};
&nbsp;&nbsp;my($h, $M) = $data-&gt;{time} =~ /(\d+):(\d+)/;
&nbsp;&nbsp;$h = 0 if $h == 12;
&nbsp;&nbsp;$h += 12 if $data-&gt;{time} =~ /PM/;
&nbsp;&nbsp;$data-&gt;{date} = &quot;$y-$m-$d $h:$M&quot;;</pre>
<p>There are a few things going on here.</p>
<p>The <tt>handle</tt> directive contains a regexp &#8212; any pages that match this regexp will have their content extracted using this configuration.  Because it&#8217;s a regexp metacharactes, like &#8220;.&#8221; need to be escaped.</p>
<p>The <tt>extract_xpath</tt> section contains directives that tell the plugin how to retrieve certain key bits of data from the page using XPath expressions.  <tt>title</tt>, <tt>body</tt>, and <tt>author</tt> are all special keys that correspond to sections of the generated RSS feed.</p>
<p>There&#8217;s a problem with the <tt>use.perl</tt> journal pages because they don&#8217;t contain the date and time the entry was published in a trivially parseable format &#8212; the information&#8217;s human readable, and split over a couple of different elements.</p>
<p>So here the <tt>day</tt> and <tt>time</tt> of the journal entry are extracted in to two separate variables.  But these need to be post-processed to get a timestamp for the feed.</p>
<p>This is where <tt>extract_after_hook</tt> comes in.  This is a block of Perl code that&#8217;s run after the data has been extracted.  In this code <tt>$data</tt> is a hash ref, with keys that match those used under <tt>extract_xpath</tt> section.</p>
<p>By this point, <tt>$data->{day}</tt> looks something like <tt>Tuesday December 05, 2006</tt>, and <tt>$data->{time}</tt> might be <tt>08:36 AM</tt>.  That month name needs to be converted to a number, hence the <tt>%months</tt> declaration, and the time needs to be normalised.  So the hour and minute value is extracted.  With use.perl the hour &#8220;12&#8243; might be midnight or midday, and all afternoon hours are indicated with &#8220;PM&#8221; in the string.  So the hour is reset to 0 if it&#8217;s 12, and then 12 is added to all times in the afternoon.</p>
<p>Finally, these values are brought together and assigned to $data->{date}, which is another special key for Plagger.</p>
<p>Here&#8217;s the <a href="http://jc.ngo.org.uk/~nik/use.perl.journals.rss">full RSS feed for use.perl journals</a>.  Feel free to use this in your aggregator, it is currently set to auto-update every 30 minutes.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('93', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2006%2F12%2F05%2Fuseperl-journals-and-full-text-feeds%2F', 'use.perl+journals+and+full+text+feeds'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_93">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2006/12/05/useperl-journals-and-full-text-feeds/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SVN::Web and Google Code Hosting</title>
		<link>http://jc.ngo.org.uk/blog/2006/11/29/svnweb-and-google-code-hosting/</link>
		<comments>http://jc.ngo.org.uk/blog/2006/11/29/svnweb-and-google-code-hosting/#comments</comments>
		<pubDate>Wed, 29 Nov 2006 07:27:56 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>svn-web</category>

		<category>subversion</category>

		<category>googlecode</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2006/11/29/svnweb-and-google-code-hosting/</guid>
		<description><![CDATA[You&#8217;re probably aware of Google&#8217;s code hosting service.  They use Subversion as their revision control system, so if you want to contribute to a project hosted there you really need a Subversion client.
I was reading the FAQ for the hosting service the other day and a particular entry struck me.

Do you have support for [...]]]></description>
			<content:encoded><![CDATA[<p>You&#8217;re probably aware of <a href="http://code.google.com/hosting/">Google&#8217;s code hosting service</a>.  They use Subversion as their revision control system, so if you want to contribute to a project hosted there you really need a Subversion client.</p>
<p>I was reading the <a href="http://code.google.com/hosting/faq.html">FAQ for the hosting service</a> the other day and a <a href="http://code.google.com/hosting/faq.html#viewvc">particular entry</a> struck me.</p>
<p><a id="more-92"></a></p>
<blockquote><p><b>Do you have support for ViewVC or similar repository-browsing tools?</b></p>
<p>This feature isn&#8217;t implemented yet, but you can still browse the latest version of your project&#8217;s code by entering the repository URL into a web browser.</p></blockquote>
<p>Since <a href="http://search.cpan.org/~nikc/SVN-Web/">SVN::Web</a> now supports (well, it does on my <a href="http://jc.ngo.org.uk/svnweb/jc/browse/nik/CPAN/SVN-Web/branches/svn-client">development site</a>, which will be released as 0.50 real soon now) accessing remote repositories, it should be pretty easy to have it talk to the repositories hosted at Google.</p>
<p>A minor wrinkle is that SVN::Web expects to be configured with a list of available repositories.  But that&#8217;s only a small code change to solve.  So I&#8217;ve done that, and put together a proof-of-concept SVN::Web installation.</p>
<p>The practical upshot of which is that if you have a project at Google Code Hosting, you can take this URL: <code>http://jc.ngo.org.uk:81/svnweb/</code>, append the name of your project, and get a decent web interface on to your repository.</p>
<p>For example, the Reconstructor project (chosen at random) gets this URL: <a href="http://jc.ngo.org.uk:81/svnweb/reconstructor">http://jc.ngo.org.uk:81/svnweb/reconstructor</a>.</p>
<p>This is very definitely a <b>proof of concept</b>, and may well disappear if it gets completely hammered, and/or starts sucking up all my hosted bandwidth.
</p>
<p class="akst_link"><a href="javascript:void(akst_share('92', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2006%2F11%2F29%2Fsvnweb-and-google-code-hosting%2F', 'SVN%3A%3AWeb+and+Google+Code+Hosting'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_92">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2006/11/29/svnweb-and-google-code-hosting/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Planet Subversion</title>
		<link>http://jc.ngo.org.uk/blog/2006/11/27/planet-subversion/</link>
		<comments>http://jc.ngo.org.uk/blog/2006/11/27/planet-subversion/#comments</comments>
		<pubDate>Mon, 27 Nov 2006 09:06:18 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>perl</category>

		<category>plagger</category>

		<category>subversion</category>

		<guid isPermaLink="false">http://jc.ngo.org.uk/blog/2006/11/27/planet-subversion/</guid>
		<description><![CDATA[I&#8217;ve been experimenting with Plagger, a tool for plugging together chains of filters, pumping RSS/ATOM feeds in one end, and getting transformed output at the other end.
This doesn&#8217;t have to be as simple as chaining a few XSLT transformations together, as Plagger filters can carry out additional actions (such as e-mailing the results to you, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been experimenting with <a href="http://www.plagger.org/">Plagger</a>, a tool for plugging together chains of filters, pumping RSS/ATOM feeds in one end, and getting transformed output at the other end.</p>
<p>This doesn&#8217;t have to be as simple as chaining a few XSLT transformations together, as Plagger filters can carry out additional actions (such as e-mailing the results to you, calling on the power of Perl modules to create summaries, and so on).</p>
<p>As a learning exercise, I&#8217;ve built <a href="http://www.planet-subversion.com/">Planet Subversion</a> (<b>edit</b> I&#8217;ve updated the URL to point to the official domain).  This takes feeds from a number of different sources and builds a &quot;Planet&quot; site from them.  And, of course, with Plagger being open source, it&#8217;s easy to <a href="http://plagger.org/trac/changeset/1859">contribute any fixes back to the author</a>.</p>
<p>Please let me know if you use Subversion and can recommend any other feeds to add.</p>
<p>If you&#8217;d like to produce your own aggregation site using Plagger, here&#8217;s the config file that I&#8217;m using for Planet Subversion.</p>
<p><a id="more-91"></a></p>
<pre>plugins:
&nbsp;&nbsp;- module: Subscription::Config
&nbsp;&nbsp;&nbsp;&nbsp;config:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;feed:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://svn-dev.blogspot.com/atom.xml
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://asdf.blogs.com/asdf/index.rdf
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://blog.red-bean.com/sussman/?feed=rss2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://www.subversionary.org/blog/martintomes
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://tortoisesvn.net/blog/feed
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://www.davidglasser.net/point/feed/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- http://arildf.spaces.live.com
&nbsp;
&nbsp;&nbsp;- module: Bundle::Planet
&nbsp;&nbsp;&nbsp;&nbsp;config:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duration: 7 days
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title: Planet Subversion
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description: Everything Subversion
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir: [set this to your preferred output directory]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url: http://www.planet-subversion.com/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;theme: sixapart-std
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stylesheet: http://bulknews.typepad.com/blog/styles.css</pre>
<p class="akst_link"><a href="javascript:void(akst_share('91', 'http%3A%2F%2Fjc.ngo.org.uk%2Fblog%2F2006%2F11%2F27%2Fplanet-subversion%2F', 'Planet+Subversion'));" title="E-mail this, post to del.icio.us, etc." id="akst_link_91">Share This</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://jc.ngo.org.uk/blog/2006/11/27/planet-subversion/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Trigger happy hosting / spam @ The Guardian</title>
		<link>http://jc.ngo.org.uk/blog/2006/11/24/trigger-happy-hosting-spam-the-guardian/</link>
		<comments>http://jc.ngo.org.uk/blog/2006/11/24/trigger-happy-hosting-spam-the-guardian/#comments</comments>
		<pubDate>Fri, 24 Nov 2006 17:16:51 +0000</pubDate>
		<dc:creator>nik</dc:creator>
		
		<category>spam</category>

		<category>g