<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Gareth Lennox</title><link>https://garethlennox.com/</link><description>Recent content on Gareth Lennox</description><language>en-us</language><copyright>Copyright © Gareth Lennox.</copyright><lastBuildDate>Tue, 01 Jun 9999 00:00:00 +0000</lastBuildDate><atom:link href="https://garethlennox.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Thoughts from ScaleConf</title><link>https://garethlennox.com/2013/05/06/thoughts-from-scaleconf/</link><pubDate>Mon, 06 May 2013 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2013/05/06/thoughts-from-scaleconf/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2013/05/06/thoughts-from-scaleconf/">Thoughts from ScaleConf&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 06 May 2013&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I went to &lt;a href="http://scaleconf.org/">ScaleConf&lt;/a> a couple of weeks ago, and have been meaning to write about some thoughts I
had, so here it is!&lt;/p>
&lt;p>The conference is, as per its name, primarily about scaling, and to be more specific, scaling software, and to be even
more specific, a lot of the talks were about scaling software in your start-up.&lt;/p>
&lt;p>Most of the speakers were from local companies, that are start-ups, or have recently grown past that stage. There were a
couple of international speakers, notably from Facebook and AWS. They have completely different problems to the rest of
us.&lt;/p>
&lt;p>It was a fascinating look at building scaling systems and I found a couple of common themes kept appearing in most, if
not all, of the talks. They seem to be good general practices, not just when you need your software to scale. Below are
the seven common themes I identified.&lt;/p>
&lt;h3 id="1-use-the-cloud">1. Use the cloud&lt;/h3>
&lt;p>This might seem obvious today, but it’s important to not underestimate the ease and speed that you can scale up using
the cloud, not to mention the cost.&lt;/p>
&lt;p>One speaker said that any small company can compete with much larger companies in terms of capacity, via the cloud,
something that was not possible 5/10 years ago.&lt;/p>
&lt;h3 id="2-make-sure-you-can-scale-horizontally">2. Make sure you can scale horizontally&lt;/h3>
&lt;p>You want to be able to drop in another server, or ten and have it just work. You cannot keep buying bigger and bigger
machines, as it starts costing large amounts of money, and there is a limit to the size you can buy. One huge server is
also a single point of failure…&lt;/p>
&lt;h3 id="3-dont-have-a-single-point-of-failure">3. Don’t have a single point of failure&lt;/h3>
&lt;p>The cloud makes this easy to do by having multiple instances or everything, and it doesn’t cost huge amounts of money. A
lot of the speakers mentioned that they still have single points of failure, but in all cases, they were actively
working to get rid of them.&lt;/p>
&lt;h3 id="4-use-caching">4. Use caching&lt;/h3>
&lt;p>Seems simple enough, but caching can make or break a system and will let you ride out waves of busyness.&lt;/p>
&lt;h3 id="5-use-queuing">5. Use queuing&lt;/h3>
&lt;p>Use queues to separate your backend processing from the front-end. This allows you to build more loosely coupled systems
with the ability to take down parts of the system without affecting the rest. Pretty much everyone speaking mentioned
that they were using some form of queuing mechanism. RabbitMQ seems to be the new hotness.&lt;/p>
&lt;h3 id="6-push-to-production-often">6. Push to production often&lt;/h3>
&lt;p>There is all sorts of talk about agile in software development, but I realised that being agile in releasing your
software is important too. Some of the speakers showed us how they deploy new versions of their software upwards of 20
times a day. Most corporates I&amp;rsquo;ve worked with, you&amp;rsquo;re lucky to get a new version into production once every 3 months.&lt;/p>
&lt;h3 id="7-every-scenario-is-different">7. Every scenario is different&lt;/h3>
&lt;p>What works for one scenario doesn’t necessarily work for others, including the things I listed above. You can probably
think of a case quite easily where the above do not apply.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Simple version numbers with git</title><link>https://garethlennox.com/2013/01/28/simple-version-numbers-with-git/</link><pubDate>Mon, 28 Jan 2013 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2013/01/28/simple-version-numbers-with-git/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2013/01/28/simple-version-numbers-with-git/">Simple version numbers with git&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 28 January 2013&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Each .net project has a version number (4 dotted numbers, e.g. 1.0.0.0). While you could leave it like that, it would
ideally point back a unique revision in your source control system.&lt;/p>
&lt;p>Unfortunately, they need to be a number, so you cannot dump the git hash in there and be done.&lt;/p>
&lt;p>There are some projects that do this for you automatically (like &lt;a href="http://versioning.codeplex.com/">MSBuild Versioning&lt;/a>),
but for &lt;strong>small projects&lt;/strong> this is typically a bit overboard.&lt;/p>
&lt;p>I usually just create a windows batch file, version.bat in the root of my projects, with the following content:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bat" data-lang="bat">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">SET&lt;/span> &lt;span style="color:#953800">version&lt;/span>&lt;span style="color:#1f2328">=&lt;/span>0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">FOR&lt;/span> &lt;span style="color:#cf222e">/F&lt;/span> &lt;span style="color:#0a3069">&amp;#34;tokens=1&amp;#34;&lt;/span> &lt;span style="color:#0a3069">%%&lt;/span>a &lt;span style="color:#cf222e">IN&lt;/span> &lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#39;git rev-list master&amp;#39;&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#cf222e">DO&lt;/span> &lt;span style="color:#cf222e">SET&lt;/span> &lt;span style="color:#cf222e">/A&lt;/span> &lt;span style="color:#953800">version&lt;/span>&lt;span style="color:#0550ae">+=&lt;/span>&lt;span style="color:#0550ae">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">FOR&lt;/span> &lt;span style="color:#cf222e">/F&lt;/span> &lt;span style="color:#0a3069">&amp;#34;tokens=*&amp;#34;&lt;/span> &lt;span style="color:#0a3069">%%&lt;/span>a &lt;span style="color:#cf222e">IN&lt;/span> &lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#39;git rev-parse HEAD&amp;#39;&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#cf222e">DO&lt;/span> &lt;span style="color:#cf222e">SET&lt;/span> &lt;span style="color:#953800">commit&lt;/span>&lt;span style="color:#1f2328">=&lt;/span>&lt;span style="color:#0a3069">%%&lt;/span>a
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">echo&lt;/span> [assembly: System.Reflection.AssemblyVersion(&lt;span style="color:#0a3069">&amp;#34;1.0.&lt;/span>&lt;span style="color:#953800">%version%&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&lt;/span>)] &lt;span style="color:#1f2328">&amp;gt;&lt;/span> src\AssemblyVersion.cs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">echo&lt;/span> [assembly: System.Reflection.AssemblyDescription(&lt;span style="color:#0a3069">&amp;#34;Compiled from &lt;/span>&lt;span style="color:#953800">%commit%&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&lt;/span>)] &lt;span style="color:#1f2328">&amp;gt;&amp;gt;&lt;/span> src\AssemblyVersion.cs
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This just gets a version number from git (basically the number of commits) and the current commit’s hash and pushes it
into a AssemblyVersion.cs file that I include with my project.&lt;/p>
&lt;p>&lt;em>Yes, using the number of commits as a version number has issues if you deploy code from different places (you will get
different version numbers because of merges), but remember – this is for small projects that you’d deploy from one place
and that you’d typically not have a build server.&lt;/em>&lt;/p>
&lt;p>I usually have a build.bat file that first calls the version.bat one, and then calls msbuild to build the solution.&lt;/p>
&lt;p>If you have a mbuild file, you could just pass in the version number and commit hash as parameters (but then, rather use
&lt;a href="http://versioning.codeplex.com/">MSBuild Versioning&lt;/a> linked above).&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Delivering all mail to a local account</title><link>https://garethlennox.com/2012/10/26/delivering-all-mail-to-a-local-account/</link><pubDate>Fri, 26 Oct 2012 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2012/10/26/delivering-all-mail-to-a-local-account/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2012/10/26/delivering-all-mail-to-a-local-account/">Delivering all mail to a local account&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 26 October 2012&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I recently
&lt;a href="http://askubuntu.com/questions/206766/local-only-sendmail-that-delivers-all-mail-to-a-directory/206775">asked a question&lt;/a>
on &lt;a href="http://askubuntu.com/">Ask Ubuntu&lt;/a>, regarding setting up my Ubuntu (12.04) virtual machine with a mail server, but
to not actually send any mail.&lt;/p>
&lt;p>What&amp;rsquo;s the point of this? Well, because I&amp;rsquo;m developing web applications that send mail, I want to test with all sorts of
different e-mail addresses, other than my own, without actually sending these test messages. Ideally all the messages
would get dumped into a single folder to me to review whenever I need to.&lt;/p>
&lt;p>I didn&amp;rsquo;t get a response (yes, I&amp;rsquo;m impatient!), but managed to work it out myself, and posted the answer to the site. I&amp;rsquo;m
putting it here for future reference. I used the postfix mail server, which is easy to install (sudo apt-get install
postfix) and configure. To get it to deliver all mail locally, you need to do two things:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Install the postfix-pcre package (sudo  apt-get install postfix-pcre)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Edit the main postfix configuration file (sudo nano /etc/postfix/main.cf file) and add the following lines, tweaking
the MYLOCALUSER value to a user on the machine (using
&lt;a href="http://askubuntu.com/questions/28850/smtp-server-to-deliver-all-mail-to-userlocalhost">an answer on AskUbuntu&lt;/a>):&lt;/p>
&lt;pre tabindex="0">&lt;code>luser_relay: MYLOCALUSER@localhost
local_recipient_maps =
&lt;/code>&lt;/pre>&lt;/li>
&lt;li>
&lt;p>Still editing the file, replace the mydestination configuration value using the value below (using an
&lt;a href="http://serverfault.com/questions/133190/host-wildcard-subdomains-using-postfix">answer on serverfault&lt;/a>) (note that
you need the postfix-pcre package installed):&lt;/p>
&lt;pre tabindex="0">&lt;code>mydestination: pcre:/etc/postfix/mydestinations
&lt;/code>&lt;/pre>&lt;/li>
&lt;li>
&lt;p>Create and edit the mydestinations file referenced above (sudo nano /etc/postfix/mydestinations) and put the
following line in it:&lt;/p>
&lt;pre tabindex="0">&lt;code>/.\*/ ACCEPT
&lt;/code>&lt;/pre>&lt;/li>
&lt;li>
&lt;p>Restart the postfix server:&lt;/p>
&lt;pre tabindex="0">&lt;code>sudo /etc/init.d/postfix restart
&lt;/code>&lt;/pre>&lt;/li>
&lt;/ol>
&lt;p>This creates a rule that basically tells postfix to treat all mail it processes as local domains. The luser_relay value
and the local_recipient_maps value work together to define the default user to deliver mail to, your local user.&lt;/p>
&lt;p>You can thereafter use whatever mail client you want, as all mail the server deals with is routed to your local
user. Obviously you shouldn&amp;rsquo;t ever do this on a server that you want to, you know, actually send mail or anything,
therefore it is primarily useful when developing software and you want to test you mail sending code.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Using Google Web Fonts</title><link>https://garethlennox.com/2012/08/07/using-google-web-fonts/</link><pubDate>Tue, 07 Aug 2012 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2012/08/07/using-google-web-fonts/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2012/08/07/using-google-web-fonts/">Using Google Web Fonts&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 07 August 2012&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>&lt;a href="http://www.google.com/webfonts">Google Web Fonts&lt;/a> is a great resource for custom web fonts. It is free and has a huge
library of fonts (508 different fonts at time of writing).&lt;/p>
&lt;p>A lot of people are saying that while the library is large, the quality of most of the fonts is not that great. While
this is true, you just have to find the high-quality fonts that do exist. There are a couple of useful sites on the web
that help you choose fonts out of the huge selection. &lt;a href="http://hellohappy.org/beautiful-web-type/">Beautiful Web Type&lt;/a> is
a great resource as is &lt;a href="http://sachagreif.com/google-webfonts-that-dont-suck/">Google Webfonts that Don&amp;rsquo;t Suck&lt;/a>.
Alternatively, just play around with the various fonts (there is a
&lt;a href="https://chrome.google.com/webstore/detail/engndlnldodigdjamndkplafgmkkencc">handy chrome plugin&lt;/a>).&lt;/p>
&lt;p>It is really easy to include whatever fonts you want in you site, just beware about having too many, as it does increase
your page size as well as not looking too good if you have tons of different fonts that don&amp;rsquo;t complement each other. A
good guide for choosing fonts is
&lt;a href="http://webdesign.tutsplus.com/articles/typography-articles/a-beginners-guide-to-pairing-fonts/">A Beginner&amp;rsquo;s Guide to Pairing Fonts&lt;/a>.&lt;/p>
&lt;p>I&amp;rsquo;ve recently changed what fonts this site uses, using Google Web Fonts; I went with
&lt;a href="http://www.google.com/webfonts/specimen/Oswald">Oswald&lt;/a> for headings, and
&lt;a href="http://www.google.com/webfonts/specimen/Lora">Lora&lt;/a> for the body copy.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Embedded ICC profiles and Firefox</title><link>https://garethlennox.com/2012/05/12/embedded-icc-profiles-and-firefox/</link><pubDate>Sat, 12 May 2012 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2012/05/12/embedded-icc-profiles-and-firefox/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2012/05/12/embedded-icc-profiles-and-firefox/">Embedded ICC profiles and Firefox&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 12 May 2012&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I have a &lt;a href="http://refracted.co.za/">separate blog&lt;/a> where I post photos I take, and I recently noticed a problem with how
the actual JPEGs display in Firefox. It was almost like they were showing the image in a lower colour
mode. All other browsers displayed the images fine.&lt;/p>
&lt;p>Here is an example using a recent photo off the blog. You can see the blurry background is cutoff in firefox.&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2012/example_firefox.jpg" alt="Firefox example" />
&lt;/figure>
&lt;p>The difference is that Firefox is one a couple of browsers in the market (Safari and possibly IE10 seem to be supporting
it too) that applies embedded ICC colour profiles in images when displaying them.&lt;/p>
&lt;p>I was saving my JPEGs with the ICC profile (sRGB) embedded in them and therefore Firefox was adjusting the colours to
match the profile, messing things up.&lt;/p>
&lt;p>I&amp;rsquo;m not 100% sure as to what is happening, but I can hazard a guess. The ICC profile is intended to remove the link
between a device dependent colour space (e.g. the camera or your screen) and an independent colour space. I think the
image is saved with the colours already converted to the target colour space, but with the profile embedded, Firefox
applies the transformation again, thereby effectively applying the conversion twice. I couldn&amp;rsquo;t find much information
about this on the web, so this is just a guess.&lt;/p>
&lt;p>The information on the web is a bit thin&amp;hellip; I did
find &lt;a href="http://www.gballard.net/psd/go_live_page_profile/embeddedJPEGprofiles.html">this page&lt;/a>, but it doesn&amp;rsquo;t seem to
explain the issue I&amp;rsquo;m having.&lt;/p>
&lt;p>So, after all that, what is the fix? Just save the image without the profile in it, and everything displays as intended,
across all browsers and image viewers that I tested on (you can also remove the profile of an existing image using tools
like &lt;a href="http://www.sno.phy.queensu.ca/~phil/exiftool/">exiftool&lt;/a>).&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>XTS-AES implementation: SectorStream</title><link>https://garethlennox.com/2012/03/22/xts-aes-implementation-sectorstream/</link><pubDate>Thu, 22 Mar 2012 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2012/03/22/xts-aes-implementation-sectorstream/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2012/03/22/xts-aes-implementation-sectorstream/">XTS-AES implementation: SectorStream&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 22 March 2012&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>As a by-product of the &lt;a href="https://bitbucket.org/garethl/xtssharp">XtsSharp project&lt;/a>, I implemented
a &lt;a href="https://bitbucket.org/garethl/xtssharp/src/0e6a81a823e9/src/XTSSharp/SectorStream.cs">SectorStream&lt;/a>, which is a
stream that reads and writes whole sectors&lt;/p>
&lt;p>(the size of which is configurable) to enable the XTS algorithm
to operate on standard .NET streams.&lt;/p>
&lt;p>I also implemented another stream based class that provides random access to an underlying SectorStream. This simulates
random access by reading and writing entire sectors at once. This stream is called (yep, you guessed
it) &lt;a href="https://bitbucket.org/garethl/xtssharp/src/0e6a81a823e9/src/XTSSharp/RandomAccessSectorStream.cs">RandomAccessSectorStream&lt;/a>.&lt;/p>
&lt;p>The result is that you can use the random access stream to wrap a SectorStream and read and write to it as if it was
just a normal .NET stream. It supports seeking to arbitrary points and reading / writing. The class handles the sector
by sector reading and writing, which when using an XTSSectorStream, encrypts (when writing) and decrypts (when reading).&lt;/p>
&lt;p>I&amp;rsquo;m not sure if this is usable outside of the XTS project, but it is completely separate code-wise, so maybe someone
will find a use for it.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>XTS-AES implementation in .NET</title><link>https://garethlennox.com/2012/03/19/xts-aes-implementation-in-.net/</link><pubDate>Mon, 19 Mar 2012 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2012/03/19/xts-aes-implementation-in-.net/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2012/03/19/xts-aes-implementation-in-.net/">XTS-AES implementation in .NET&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 19 March 2012&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I&amp;rsquo;ve been meaning to write about this for some time, but laziness, procrastination and work have managed to get in the
way.&lt;/p>
&lt;p>DISCLAIMER: I am not a cryptographer, cryptography is something that interests me and the library is a proof of concept;
you use it at your own risk.&lt;/p>
&lt;p>I recently (i.e. a year ago!) wrote an implementation of
the &lt;a href="https://bitbucket.org/garethl/xtssharp">XTS algorithm in .NET (C#)&lt;/a>. I had
asked &lt;a href="http://stackoverflow.com/questions/1558854/xts-aes-mode-in-c-sharp">a question on stackoverflow&lt;/a>, but didn&amp;rsquo;t get
much of a response. The only other implementations I found were in C or C++.&lt;/p>
&lt;p>I eventually implemented it myself by looking at
the &lt;a href="http://libtom.org/?page=features&amp;amp;newsitems=5&amp;amp;whatfile=crypt">LibTomCrypt&lt;/a> library as well as the
actual &lt;a href="http://grouper.ieee.org/groups/1619/email/pdf00086.pdf">IEEE standard document&lt;/a>. The implementation supports
AES-128 and AES-256 and is licensed under the BSD license, so do with it what you will!.&lt;/p>
&lt;p>XTS&amp;rsquo;s main purpose is to enable encryption on block level devices (e.g. hard drives) while allowing random read / write
access to the data. The key here is that each block can be encrypted / decrypted without touching the other blocks.
Standard modes
(like &lt;a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29">CBC&lt;/a>) chain the
blocks together, so to decrypt block 1000, you have to decrypt the previous 999. Encrypting each block separately using
a mode like ECB is not secure as two blocks with the same content will encrypt to the same cypher text.&lt;/p>
&lt;p>XTS gets around this problem by chaining two encryption steps together with a tweak step in the middle. The key input
that is quite different from other cipher block modes in that XTS uses the sector number as part of the tweak step. This
works quite well, as it is easy to calculate the sector number. Most available disk encryption software uses XTS mode.&lt;/p>
&lt;p>The library uses the built in .NET AES implementation internally, and coordinates the two AES encryption transforms
along with the actual tweak.&lt;/p>
&lt;p>You can see my implementation
in &lt;a href="https://bitbucket.org/garethl/xtssharp/src/7d45bc6b975c/src/XTSSharp/XtsCryptoTransform.cs">my bitbucket repository&lt;/a>,
and the LibTomCrypt one
in &lt;a href="https://github.com/libtom/libtomcrypt/blob/master/src/modes/xts/xts_encrypt.c">their github repository&lt;/a>. The entire
algorithm is basically implemented in the single XtsCryptoTransform class. It is actually simpler than the LibTom one
due to the nature of the .NET ICryptoTransform interface being the same for encryption / decryption. It can also be
extended quite easily to use other encryption algorithms, as it depends on the ICryptoTransform interface only.&lt;/p>
&lt;p>The library has unit tests that test it against the test vectors in Annex B in
the &lt;a href="http://grouper.ieee.org/groups/1619/email/pdf00086.pdf">IEEE standards document&lt;/a> (which it obviously matches!)&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>A new home for my blog</title><link>https://garethlennox.com/2012/03/10/a-new-home-for-my-blog/</link><pubDate>Sat, 10 Mar 2012 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2012/03/10/a-new-home-for-my-blog/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2012/03/10/a-new-home-for-my-blog/">A new home for my blog&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 10 March 2012&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>This site has now moved to it&amp;rsquo;s own domain (&lt;a href="https://garethlennox.com/">garethlennox.com&lt;/a>), rather than sitting in a
subdirectory under another domain.&lt;/p>
&lt;p>I managed to move it in the space of a couple of hours, without too many hassles. The main problem was that wordpress
doesn&amp;rsquo;t like to have it&amp;rsquo;s main url changed from underneath it, so I had to get into the database and tweak some values.
There is a good guide in the &lt;a href="http://codex.wordpress.org/Moving_WordPress">wordpress codex&lt;/a> on how to do this.&lt;/p>
&lt;p>Otherwise, barring some obscure file permission problems, it was very straight forward.&lt;/p>
&lt;p>One other benefit of having my own domain is that I get to set the favicon for it, which is a smaller version of my
logo. I used &lt;a href="http://www.favicon.cc/">this handy tool&lt;/a> to convert the favicon into a .ico format.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>New design!</title><link>https://garethlennox.com/2011/12/20/new-design/</link><pubDate>Tue, 20 Dec 2011 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2011/12/20/new-design/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2011/12/20/new-design/">New design!&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 20 December 2011&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Finally, I&amp;rsquo;ve updated the design of this site, to brand-new spanking HTML5, including a fluent layout, that adjusts for
larger and smaller screens&lt;/p>
&lt;p>(it looks great on a phone too!). I created the previous design in 2005, so it
was time for a refresh.&lt;/p>
&lt;p>The site should work in any modern browser, as well as reasonably modern phone browsers. It even looks kinda ok in IE6!&lt;/p>
&lt;p>I am still running &lt;a href="http://wordpress.org/">Wordpress&lt;/a>, with a large bunch of plugins. The new design is based off the
&lt;a href="http://starkerstheme.com/">Starkers theme&lt;/a> - an extremely minimalistic theme (to see how minimialistic,
&lt;a href="http://starkerstheme.com/demo/">see the demo&lt;/a>). It is awesome in that it gives you the HTML framework without any CSS.
The end-result? Much less CSS than if you&amp;rsquo;d started with an existing theme.&lt;/p>
&lt;p>The design is intended to be minimal as well, with a focus on the content. I&amp;rsquo;ve stripped out all the twitter and
delicious feeds. If you want those, links to them are at the bottom of the page.&lt;/p>
&lt;p>Notable plugins that make this site run:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://ocaoimh.ie/wp-super-cache/">WP Super Cache&lt;/a>: The standard Wordpress caching plugin. I&amp;rsquo;ve been using this for
years, and it works really well.&lt;/li>
&lt;li>&lt;a href="http://omninoggin.com/wordpress-plugins/wp-minify-wordpress-plugin/">WP Minify&lt;/a>: Combines and minifies all the CSS
and javascript files into single requests. This one is new, so we&amp;rsquo;ll see how it goes. Seems to work nicely.&lt;/li>
&lt;li>&lt;a href="http://akismet.com/">Akismet&lt;/a>: For comment spam. Also brilliant.&lt;/li>
&lt;/ul>
&lt;p>It always seems that re-designing this site is way more fun than actually posting on it, which is rather worrying. As
usual, I&amp;rsquo;m going to try to find time to post here more often&amp;hellip;&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Picasa: Moving albums to another computer</title><link>https://garethlennox.com/2011/10/04/picasa-moving-albums-to-another-computer/</link><pubDate>Tue, 04 Oct 2011 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2011/10/04/picasa-moving-albums-to-another-computer/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2011/10/04/picasa-moving-albums-to-another-computer/">Picasa: Moving albums to another computer&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 04 October 2011&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Just spend hours working out how to do this. If you&amp;rsquo;re moving pictures to another PC or your Picasa db gets broken, you
may lose all your albums.&lt;/p>
&lt;p>The album information is stored alongside the Picasa database, in xml files with
a .pal extension, which is irritating - you have to back up that folder too.&lt;/p>
&lt;p>It is very simple to get your albums back, just do what this thread says, and all works fine:
&lt;a href="http://www.google.com/support/forum/p/Picasa/thread?tid=4267d3f621027f95&amp;amp;hl=en">http://www.google.com/support/forum/p/Picasa/thread?tid=4267d3f621027f95&amp;amp;hl=en&lt;/a>.
All you have to do is copy your .pal files into any folder that Picasa is watching, and it will pick them right up.&lt;/p>
&lt;p>This guide worked for me (copied here in case the thread disappears):&lt;/p>
&lt;blockquote>
&lt;p>Transfer album definitions from Computer A to Computer B. There are the same photos, but placed in different location
on the destination computer.&lt;/p>
&lt;ol>
&lt;li>Edit the Albums in Picasa on Computer A&lt;/li>
&lt;li>Exit the Picasa on Computer A. The PAL files are created in Picasa2Albums by this.&lt;/li>
&lt;li>Copy files to temporary folder and edit the paths to the photos in all the PAL files to conform the photos location
on the Computer B.&lt;/li>
&lt;li>Start and exit Picasa on Computer B to refresh the Album status in the Picasa internal database&lt;/li>
&lt;li>Start Picasa.&lt;/li>
&lt;li>All referenced photos from edited PALs have to be visible for Picasa otherwise the Albums are not crated or empty.
In order that, make the photos visible for Picasa in Tools -&amp;gt; Folder Manager &amp;hellip;&lt;/li>
&lt;li>Put the PAL files to any monitored folder. If it is &amp;ldquo;Scan Once&amp;rdquo; folder, you have to trigger licking by opening
Folder Manager again - just enter, end exit by OK button.&lt;/li>
&lt;li>The new Albums are imported to Picasa on Computer B having all photos inside. Source PAL files are deleted.&lt;/li>
&lt;/ol>&lt;/blockquote>
&lt;p>All the other crap you&amp;rsquo;ll find around the net about changing the dbid to null and stuff doesn&amp;rsquo;t work in the latest
version of Picasa.&lt;/p>
&lt;p>Hopefully the next time this happens to me, I&amp;rsquo;ll find my own blog post!&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>8 requirements that good backup software needs to fulfil</title><link>https://garethlennox.com/2010/05/20/8-requirements-that-good-backup-software-needs-to-fulfil/</link><pubDate>Thu, 20 May 2010 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2010/05/20/8-requirements-that-good-backup-software-needs-to-fulfil/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2010/05/20/8-requirements-that-good-backup-software-needs-to-fulfil/">8 requirements that good backup software needs to fulfil&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 20 May 2010&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I’ve been thinking about backup solutions, and have been trying to find one that fits what I need.&lt;/p>
&lt;p>I have
yet to find one, and this post is the first step in outlining what I need (and hopefully what other people need), with
the end goal of building the perfect backup solution.&lt;/p>
&lt;p>(disclaimer: these are 8 requirements for me, yours may differ!)&lt;/p>
&lt;p>Something to remember: &lt;strong>When&lt;/strong> your hard drive dies, do you have your data safely stored somewhere else? A good test
would be if all the hard drives in your pc all stopped working right now, would you lose any critical or valuable data?
Do you have backups? Can you restore your backups? What about if your whole house burned down?&lt;/p>
&lt;p>I’ve found that available backup software out there is either to complicated, doesn’t do what I want, or too expensive.
I’ve listed out what I feel are &lt;strong>my&lt;/strong> requirements for backup software (which means that they’re probably not your
requirements!). Note that since my primary machine is running Windows, I’m looking at requirements that Windows
supports.&lt;/p>
&lt;p>I don’t need a full disk backup, rather on a file-by-file basis. &lt;strong>When&lt;/strong> my drive crashes, I’d probably want to use the
opportunity to re-install my operating system anyway.&lt;/p>
&lt;h3 id="1-simple-and-easy-to-use">1. Simple and easy to use&lt;/h3>
&lt;p>Obviously all software should be easy to use, but why are a lot of backup solutions so complex? Ask me what to backup,
where to store the backup and how often to run. Otherwise, leave me alone (obviously if there is a problem, let me
know!).&lt;/p>
&lt;h3 id="2-simple-backup-format">2. Simple backup format&lt;/h3>
&lt;p>I should be able to open windows explorer, and view the files in a backup set without having to run any special
software. This also helps with the first requirement – if your files are stored as files on the drive, anything &lt;em>should&lt;/em>
be able to read them. When you lose your main drive, it makes it easier if you can plug in your backup drive, and just
copy files off it.&lt;/p>
&lt;h3 id="3-actually-backup-and-restore-your-files">3. Actually backup (and restore!) your files&lt;/h3>
&lt;p>This seems obvious, but I’ve seen backup solutions that will silently backup all your files, but then barf when asked to
restore them (looking at you, Windows Backup). The only way to be sure is to try restore your data at regular intervals,
no matter which system you use. If the storage format is simple, as above, this is less of an issue, but you should
still test it on a regular basis!&lt;/p>
&lt;h3 id="4-stay-out-of-my-way">4. Stay out of my way&lt;/h3>
&lt;p>You should not have to remember to run a backup. Backup software should run automatically, and quietly in the
background. Once you’ve scheduled it, it should do the rest. Disconnecting an external drive half way through a backup
should not cause any problems when you plug the drive in again – it should carry on, ideally where it left off.&lt;/p>
&lt;h3 id="5-handle-multiple-destinations">5. Handle multiple destinations&lt;/h3>
&lt;p>I would like to backup to external hard drives, USB flash drives and network computers. The software should
automatically handle things like drive letter changes for external USB drives.&lt;/p>
&lt;p>I want to define a set of files to backup, then point the software at multiple places. When plugging in a USB drive, the
software should automatically kick off a backup if one is scheduled. When connecting to a network, if the destination
machine is available, start the backup.&lt;/p>
&lt;h3 id="6-keep-history">6. Keep history&lt;/h3>
&lt;p>Being able to go back a couple of months and retrieve a file from then is very handy. The software should do intelligent
diffing as well as cleanup of old backup sets. If I’ve changed one 1MB file within of a couple of hundred gigabytes of
files, I don’t expect the next backup to take much more than 1MB of extra space.&lt;/p>
&lt;h3 id="7-offline">7. Offline&lt;/h3>
&lt;p>I have too much data to realistically store online. Living in South Africa exacerbates it because we have such
constrained bandwidth availability (e.g. ADSL with 3GB limit). An online backup solution, while nice, is not really an
option for most South Africans. If you have a couple of megabytes of word docs, then by all means install something like
&lt;a href="http://www.dropbox.com/">Dropbox&lt;/a> or &lt;a href="http://www.sugarsync.com/">SugarSync&lt;/a> and be done.&lt;/p>
&lt;h3 id="8-quick">8. Quick&lt;/h3>
&lt;p>Obviously there is a limit to how quick backup software can be – it still needs to enumerate over all files you’re
choosing to backup, but a backup of a couple of hundred changed files (from a typical day of work) should take under 5
minutes to complete.&lt;/p>
&lt;h3 id="other-nice-to-have-features">Other nice-to-have features&lt;/h3>
&lt;p>While these would be nice, they are not critical for me at the moment.&lt;/p>
&lt;p>&lt;strong>Encryption:&lt;/strong> Encrypting your files would be nice, but this would break the “Simple format” requirement above. Maybe
have an external usb drive encrypted using &lt;a href="http://www.truecrypt.org/">TrueCrypt&lt;/a>?&lt;/p>
&lt;p>&lt;strong>Handle locked files:&lt;/strong> Files that are in use should also be backed up. This would involve using Volume Shadow Copy.&lt;/p>
&lt;p>Primarily, a backup solution needs to be simple, just work and stay out of my way. Anything I’ve left out?&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Wallpaper goodness</title><link>https://garethlennox.com/2010/02/15/wallpaper-goodness/</link><pubDate>Mon, 15 Feb 2010 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2010/02/15/wallpaper-goodness/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2010/02/15/wallpaper-goodness/">Wallpaper goodness&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 15 February 2010&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I&amp;rsquo;ve uploaded some &lt;a href="http://refracted.org/wallpapers/">hi-res wallpapers&lt;/a> on
&lt;a href="http://refracted.org/">my photoblog site&lt;/a>, from photos I&amp;rsquo;ve taken. Have a look, I think they&amp;rsquo;re quite good!&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2010/cascade_300x200.jpg" alt="" />
&lt;/figure>&lt;/div>
&lt;/article></description></item><item><title>On Mono</title><link>https://garethlennox.com/2009/09/07/on-mono/</link><pubDate>Mon, 07 Sep 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/09/07/on-mono/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/09/07/on-mono/">On Mono&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 07 September 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>So, I’ve been playing around with &lt;a href="http://www.mono-project.com/">Mono&lt;/a> on a virtual machine for a while now, and want to
just put down some thoughts.&lt;/p>
&lt;p>Note that this won’t be an in-depth review of Mono, but just my initial
experiences coming from a MS .net background.&lt;/p>
&lt;p>(for those of you that don’t know, Mono is an open-source implementation of the .net CLR.
&lt;a href="http://www.mono-project.com/What_is_Mono">Go here for more details&lt;/a>. It is actually quite a bit more than that, but
coming from using .net, that is the part the interests me – at least at the moment.)&lt;/p>
&lt;p>Firstly, one of the interesting things about Mono, is that you can take an assembly compiled using Microsoft&amp;rsquo;s tools,
and run it under Mono, &lt;em>without any changes&lt;/em>. Obviously, if you’re talking to the windows registry or using MS specific
p-invoke calls, it wont work, but if your code is 100% managed, the chance that it will just work is pretty high.&lt;/p>
&lt;h3 id="tooling">Tooling&lt;/h3>
&lt;p>In terms of actually developing directly on Linux and using the Mono tools (rather than the Microsoft ones), there is an
IDE called &lt;a href="http://monodevelop.com/">MonoDevelop&lt;/a> that comes very close to the functionality of Visual Studio – in
places its better (it can even open and save Visual Studio solutions and projects).&lt;/p>
&lt;p>All the other usual command line tools are there, most importantly, there is a MSBuild clone called x-build, which lets
you use your existing build scripts.&lt;/p>
&lt;p>And something that is important for me, &lt;a href="http://nunit.org/">NUnit&lt;/a> runs fine on mono.&lt;/p>
&lt;p>For porting existing projects to Mono, there is a tool, called &lt;a href="http://mono-project.com/MoMA">MoMA&lt;/a>, which scans your
source code, flagging any areas it identifies as being a potential problem.&lt;/p>
&lt;h3 id="benefits">Benefits&lt;/h3>
&lt;p>The most obvious one is that of licensing. Since Mono is open-source, and runs on an open-source operating system, there
are zero licensing costs. This is attractive if you’re wanting to have multiple servers running your application.
Windows licenses for 20 servers is a non-trivial cost.&lt;/p>
&lt;p>Mono is also cross-platform. It runs in environments and on devices where you won’t find the Microsoft .net framework.
Taken from the mono site:&lt;/p>
&lt;blockquote>
&lt;p>Mono is built to be cross platform. Mono runs on &lt;a href="http://www.mono-project.com/Mono:Linux">Linux&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:Windows">Microsoft Windows&lt;/a>, &lt;a href="http://www.mono-project.com/Mono:OSX">Mac OS X&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:BSD">BSD&lt;/a>, and &lt;a href="http://www.mono-project.com/Mono:Solaris">Sun Solaris&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:Wii">Nintendo Wii&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:PlayStation3">Sony PlayStation 3&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:Iphone">Apple iPhone&lt;/a>. It also runs on &lt;a href="http://www.mono-project.com/Mono:X86">x86&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:AMD64">x86-64&lt;/a>, &lt;a href="http://www.mono-project.com/Mono:IA64">IA64&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:PowerPC">PowerPC&lt;/a>, &lt;a href="http://www.mono-project.com/Mono:SPARC">SPARC (32)&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:ARM">ARM&lt;/a>,
&lt;a href="http://www.mono-project.com/index.php?title=Mono:Alpha&amp;amp;action=edit">Alpha&lt;/a>,
&lt;a href="http://www.mono-project.com/Mono:S390">s390, s390x (32 and 64 bits)&lt;/a> and more. Developing your application with Mono
allows you to run on nearly any computer in existence.&lt;/p>&lt;/blockquote>
&lt;h3 id="distribution">Distribution&lt;/h3>
&lt;p>I’m not sure about older versions, but the latest version of &lt;a href="http://www.ubuntu.com/">Ubuntu&lt;/a> has Mono installed
already. A couple of the pre-installed applications are written in C#.&lt;/p>
&lt;p>To be honest, I’ve only used Mono under Ubuntu, so cannot comment on its availability in other distributions, but the
Mono website &lt;a href="http://www.go-mono.com/mono-downloads/download.html">recommends&lt;/a> &lt;a href="http://www.opensuse.org/">openSUSE&lt;/a>.&lt;/p>
&lt;h3 id="conclusion">Conclusion&lt;/h3>
&lt;p>So, in conclusion, I’m very impressed, well done guys. I’ve not yet had time to take one of our larger projects and get
it running on Mono, but that&amp;rsquo;s the next step.&lt;/p>
&lt;p>This is more a note to myself, but below is a list of things I want to investigate further around Mono:&lt;/p>
&lt;ul>
&lt;li>Ease of porting a largish existing application to Mono&lt;/li>
&lt;li>Do common frameworks run on Mono? (things like &lt;a href="http://www.asp.net/mvc/">ASP.NET MVC,&lt;/a>
&lt;a href="http://nhforge.org/">NHibernate&lt;/a>, &lt;a href="http://www.castleproject.org/container/index.html">Castle Windsor&lt;/a> etc)&lt;/li>
&lt;li>Windows Forms support (this was spotty when I looked at it a couple of years ago – its meant to be better)&lt;/li>
&lt;li>Performance vs the Microsoft stack&lt;/li>
&lt;/ul>&lt;/div>
&lt;/article></description></item><item><title>MSI version matching upgrade woes</title><link>https://garethlennox.com/2009/07/08/msi-version-matching-upgrade-woes/</link><pubDate>Wed, 08 Jul 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/07/08/msi-version-matching-upgrade-woes/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/07/08/msi-version-matching-upgrade-woes/">MSI version matching upgrade woes&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 08 July 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>We&amp;rsquo;re distributing our .net application using Microsoft&amp;rsquo;s MSI installer technology (using the very powerful
&lt;a href="http://wix.sourceforge.net/">WiX&lt;/a> to do it).&lt;/p>
&lt;p>We&amp;rsquo;ve recently seen a problem with the installer not upgrading older versions, but rather just installing on top of the
existing version, which results in the application being listed twice in the &amp;ldquo;Add/remove programs&amp;rdquo; (Programs and
Features in Vista) section, one for each version. This results in weird things happening, like uninstalling one of them
leaves the other one still installed with all the application files removed.&lt;/p>
&lt;p>I ensured that we kept the same upgrade guid, with the version number incrementing, but all looked good. After searching
and trying different things, I finally found
&lt;a href="http://msdn.microsoft.com/en-us/library/aa372379%28VS.85%29.aspx">this gem&lt;/a>, hidden away in the MS documentation:&lt;/p>
&lt;blockquote>
&lt;p>Note that Windows Installer uses only the first three fields of the product version. If you include a fourth field in
your product version, the installer ignores the fourth field.&lt;/p>&lt;/blockquote>
&lt;p>Why?!??&lt;/p>
&lt;p>Our version numbers are in the order of 3.2.0.1234, 3.2.0.1456 (where the 4th number increments based on the Subversion
revision number). The installer was seeing the version numbers as 3.2.0, i.e. the same, and not uninstalling the old
version. Changing the installer version number to 3.2.1234 fixes this.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>WP Super Cache not caching (solution)</title><link>https://garethlennox.com/2009/07/01/wp-super-cache-not-caching-solution/</link><pubDate>Wed, 01 Jul 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/07/01/wp-super-cache-not-caching-solution/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/07/01/wp-super-cache-not-caching-solution/">WP Super Cache not caching (solution)&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 01 July 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>The WP Super Cache plugin for Wordpress is a pretty awesome plugin. The other day I was having problems with it not
doing any caching&lt;/p>
&lt;p>and spitting out the following just &lt;em>before&lt;/em> the head tag (where the wp_head() call is):&lt;/p>
&lt;pre>&lt;code>&amp;lt;!-- Page not cached by WP Super Cache. No closing HTML tag. Check your theme. --&amp;gt;
&lt;/code>&lt;/pre>
&lt;p>This was very odd. Everything I could find on the web regarding this problem was seeing this tag &lt;em>at the end&lt;/em> of the
html. Eventually I found a post that sounded similar to mine (and of course now I cannot find it again, unfortunately).
It mentioned a plug-in using output buffering incorrectly. This makes sense, as looking in the source code of WP Super
Cache, it outputs the message above in its output buffer handler if it cannot find a &lt;/html> closing tag. Needless to
say, after a couple of hours fiddling, it turns out that it was a plug-in that &lt;em>I&lt;/em> had written especially for the site,
and it was doing exactly what the post mentioned (i.e. it was calling &lt;code>ob_end_flush()&lt;/code> without calling &lt;code>ob_start()&lt;/code>).&lt;/p>
&lt;p>So it was all my fault, and I&amp;rsquo;ll probably do it in the future, hence this post!&lt;/p>
&lt;p>So, note to self: If you see this in the future, check the plug-ins.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Don’t use @@IDENTITY</title><link>https://garethlennox.com/2009/05/26/dont-use-@@identity/</link><pubDate>Tue, 26 May 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/05/26/dont-use-@@identity/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/05/26/dont-use-@@identity/">Don’t use @@IDENTITY&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 26 May 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>If you’re using SQL Server, and you’re inserting records into a table with an auto increment primary key, I suggest you
don’t use @@IDENTITY to retrieve the previously inserted Id.&lt;/p>
&lt;p>Rather use SCOPE_IDENTITY().&lt;/p>
&lt;p>The reason for this is that @@IDENTITY gives you the last generated Id in the &lt;em>current session&lt;/em> vs. SCOPE&lt;em>IDENTITY()
gives you the last generated Id in the _current scope&lt;/em>.&lt;/p>
&lt;p>The current session includes any triggers that run on the table after the insert. The current scope is just the current
stored procedure that you’re in.&lt;/p>
&lt;p>We were bitten by this recently. We were using @@IDENTITY when inserted into a table that is replicated. Upon insert the
replication trigger was firing, inserting a record somewhere else. @@IDENTITY was giving us the identity of the record
the trigger inserted.&lt;/p>
&lt;p>Changing the @@IDENTITY to SCOPE_IDENTITY() fixed the problem.&lt;/p>
&lt;p>This was even nastier in that by total fluke, the identity was matching a record that already existed, so when we used
the retrieved identity to insert into another table, we didn’t violate the foreign key constraint.&lt;/p>
&lt;p>Lesson learnt!&lt;/p>
&lt;p>&lt;strong>Update: I&amp;rsquo;ve found a page with an
&lt;a href="http://www.sqlteam.com/article/alternatives-to-identity-in-sql-server-2000">in-depth look at the different techniques&lt;/a>.
Its for SQL Server 2000, but applies to 2005/2008 too.&lt;/strong>&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Google and search ranking</title><link>https://garethlennox.com/2009/05/04/google-and-search-ranking/</link><pubDate>Mon, 04 May 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/05/04/google-and-search-ranking/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/05/04/google-and-search-ranking/">Google and search ranking&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 04 May 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I&amp;rsquo;ve recently finished a new site for a client, and in the process of developing, I uploaded a test site to a web server
for the client to review.&lt;/p>
&lt;p>Since going live with the actual site, I left the test site up and running (in
the assumption that its less effort to leave it up than to take it down).&lt;/p>
&lt;p>Unfortunately, google managed to find the test site and ranked it higher than the proper site for a couple of the
keywords. Not good! Its a simple fix to put in a mod_rewrite redirect rule, but its quite incredible how quickly google
managed to find a site that has no incoming links.&lt;/p>
&lt;p>I have a feeling that its related to the site map plugin that we&amp;rsquo;re using for wordpress, I think that it pinged google
when we were developing the site, and google happily went along and indexed the site.&lt;/p>
&lt;p>So, if you&amp;rsquo;re developing a site, and put up a test version, make sure that you either take it down when making the site
live, or ensure that it redirects to the correct site.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>SQL Compact 3.5 Performance and NHibernate</title><link>https://garethlennox.com/2009/04/07/sql-compact-3.5-performance-and-nhibernate/</link><pubDate>Tue, 07 Apr 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/04/07/sql-compact-3.5-performance-and-nhibernate/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/04/07/sql-compact-3.5-performance-and-nhibernate/">SQL Compact 3.5 Performance and NHibernate&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 07 April 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>We&amp;rsquo;re using SQL Compact 3.5 in a smart client desktop application, talking to it with NHibernate and are experiencing
performance problems in a couple of places.&lt;/p>
&lt;p>In general, we&amp;rsquo;re very happy with the database, it is most of the time pretty fast, and easy to work with. The fact that
it runs within our process also helps, as its easy to install and use. This is especially useful, as we are going to be
running on relatively low-spec machines (laptops with 500MB ram).&lt;/p>
&lt;p>We are however seeing a performance problem in SELECT statements with multiple joins (&amp;gt; 5).&lt;/p>
&lt;p>&lt;a href="http://msdn.microsoft.com/en-us/library/ms172432.aspx">This article&lt;/a> warns:&lt;/p>
&lt;blockquote>
&lt;p>In general, if a significant number of your queries require joins of more than five or six tables, you should consider
denormalization.&lt;/p>&lt;/blockquote>
&lt;p>We are seeing queries that take around 4 minutes, whereas running the same query on a proper sql server takes less than
a second.&lt;/p>
&lt;p>When dumping out the query plans, and reviewing it, we are seeing in most cases, a full table scan taking place, and
joining of all rows before filtering. Running the same query on the full sql server (with the same schema), it uses the
indexes, and filters as expected. I’m going to demonstrate this issue, and a possible solution to the problem (tests
were done using SQL Compact 3.5 SP1).&lt;/p>
&lt;p>I’ve created a simple schema, as defined in the diagram below (should be pretty familiar):&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2009/sql-compact-35-1.png" alt="table diagram" />
&lt;/figure>
&lt;p>(all tables had 1000 records in them, with the exception of the order_line table, which had ~16 000 records)&lt;/p>
&lt;p>I’m going to use the following query, which is a bit contrived, but it is complex enough to display the issue:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">SELECT&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>name&lt;span style="color:#1f2328">,&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">COUNT&lt;/span>&lt;span style="color:#1f2328">([&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">].&lt;/span>id&lt;span style="color:#1f2328">)&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">AS&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_count&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">FROM&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">LEFT&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">OUTER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">JOIN&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">]&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">ON&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">].&lt;/span>id&lt;span style="color:#1f2328">:&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#1f2328">.&lt;/span>order_id&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">LEFT&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">OUTER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">JOIN&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">ON&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>id&lt;span style="color:#1f2328">:&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#1f2328">.&lt;/span>product_id&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">WHERE&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">].&lt;/span>id&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">IN&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#39;{list of ~100 integers}&amp;#39;&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">AND&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>quantity_in_stock&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#0550ae">&amp;lt;&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#1f2328">.&lt;/span>quantity&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">GROUP&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">BY&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>name&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">ORDER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">BY&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_count&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">DESC&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>name&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In SQL Compact, this generates the following query plan:&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2009/sql-compact-35-2.png" alt="Initial query plan" />
&lt;/figure>
&lt;p>On the right of the query plan, you can see it joining the order and order&lt;em>line tables (takes ~97% of the time). The
problem is that it does this join _before&lt;/em> it filters out the orders, thereby reading all the records in the order_line
table (which is obviously big!). This query runes noticeably slower with more data. Running the query on the full SQL
Server results in it using the indexes as expected.&lt;/p>
&lt;p>The solution to this, is to manually optimize the query yourself, instead of relying on the database engine to do it for
you, by removing the LEFT JOINs and inverting the query, using INNER JOINs rather, to force the engine to filter rows
out as early as possible (you’d usually write the query like this anyway, if you were doing it by hand, but remember,
we’re using NHibernate to generate the query).&lt;/p>
&lt;p>Here is the above query, optimized:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">SELECT&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>name&lt;span style="color:#1f2328">,&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">COUNT&lt;/span>&lt;span style="color:#1f2328">([&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">].&lt;/span>id&lt;span style="color:#1f2328">)&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">AS&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_count&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">FROM&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">]&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">INNER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">JOIN&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">ON&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#1f2328">.&lt;/span>order_id&lt;span style="color:#1f2328">:&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">].&lt;/span>id&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">INNER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">JOIN&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">ON&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>id&lt;span style="color:#1f2328">:&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#1f2328">.&lt;/span>product_id&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">WHERE&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#cf222e">order&lt;/span>&lt;span style="color:#1f2328">].&lt;/span>id&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">IN&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#39;{list of ~100 integers}&amp;#39;&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">AND&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>quantity_in_stock&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#0550ae">&amp;lt;&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_line&lt;span style="color:#1f2328">.&lt;/span>quantity&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">GROUP&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">BY&lt;/span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>name&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">ORDER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">BY&lt;/span>&lt;span style="color:#fff"> &lt;/span>order_count&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">DESC&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>product&lt;span style="color:#1f2328">.&lt;/span>name&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>and the corresponding query plan:&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2009/sql-compact-35-3.png" alt="Better query plan" />
&lt;/figure>
&lt;p>If you examine the query plan, you’ll notice that it’s filtering the rows up front, rather than joining and then
filtering.&lt;/p>
&lt;p>So, in conclusion, it doesn’t seem that SQL Compact optimizes LEFT JOINs properly, and you have to optimize the query
yourself to avoid table scans and poor performance.&lt;/p>
&lt;p>One important fact to note is that we’re using NHibernate to perform the querying, and its generating sql with lots of
LEFT JOINs in it (nothing wrong with that, most databases optimize this quite well). The number of joins are determined
by what base object you choose to query on, and how many values from other objects you’re pulling back.&lt;/p>
&lt;p>We’ve since replaced the generated queries that show this performance problem with hard-coded named queries, written
with inner joins as described above.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Empty unit tests</title><link>https://garethlennox.com/2009/03/10/empty-unit-tests/</link><pubDate>Tue, 10 Mar 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/03/10/empty-unit-tests/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/03/10/empty-unit-tests/">Empty unit tests&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 10 March 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I was reviewing some code, and noticed a couple of unit tests that had &lt;code>TODO&lt;/code> comments in them (and no code).&lt;/p>
&lt;p>The problem is that when running these tests, they were passing. Someone reading the list of tests would assume that the
test was testing what it claimed to be testing, when in actual fact its doing nothing.&lt;/p>
&lt;p>The first option to avoid this problem is to not actually create test methods until you’re ready to implement them.&lt;/p>
&lt;p>I know I like to sometimes lay out a list of tests I want to implement before actually writing them. If you want to do
this, then I suggest you create the methods, but ensure that the test is ignored (in nUnit, put an [Ignore] attribute
onto the method), or that it fails (in nUnit, Assert.Fail). This is especially important if you’re going to commit to
your source control system your partially complete tests.&lt;/p>
&lt;p>Doing it this way will ensure that&lt;/p>
&lt;ol>
&lt;li>You don’t forget that you need to implement the test.&lt;/li>
&lt;li>That someone doesn’t think that something is being tested when in actual fact it isn’t.&lt;/li>
&lt;/ol>&lt;/div>
&lt;/article></description></item><item><title>Using Yahoo Pipes to aggregate feeds</title><link>https://garethlennox.com/2009/03/10/using-yahoo-pipes-to-aggregate-feeds/</link><pubDate>Tue, 10 Mar 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/03/10/using-yahoo-pipes-to-aggregate-feeds/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/03/10/using-yahoo-pipes-to-aggregate-feeds/">Using Yahoo Pipes to aggregate feeds&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 10 March 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I’ve got a list of links in the sidebar of this blog. What is not obvious is that this list is an aggregated list of
links that come from multiple sources.&lt;/p>
&lt;p>At the moment, I mark links as interesting from two sources:&lt;/p>
&lt;figure class="right">
&lt;img src="https://garethlennox.com/posts/2009/pipe.png" alt="Pipe" />
&lt;/figure>
&lt;ul>
&lt;li>&lt;a href="http://delicious/gareth">Delicious&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.google.com/reader/shared/07831905801884749627">Google Reader (shared items)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Ideally, I don’t want to have 2 lists on the side, especially when most items I both bookmark in Delicious and share in
Google Reader.&lt;/p>
&lt;p>Enter Yahoo Pipes. Its an incredibly easy-to-use and powerful tool. You can see the pipe I’ve created here:
&lt;a href="http://pipes.yahoo.com/pipes/pipe.info?_id=wAcslJ753RGkTFabBR50VA" title="http://pipes.yahoo.com/pipes/pipe.info?_id=wAcslJ753RGkTFabBR50VA">http://pipes.yahoo.com/pipes/pipe.info?_id=wAcslJ753RGkTFabBR50VA&lt;/a>.
If you click the “View&amp;quot; Source” link you can see how its put together.&lt;/p>
&lt;p>The general idea is to:&lt;/p>
&lt;ol>
&lt;li>add multiple sources (fetch feed)&lt;/li>
&lt;li>union them together into one feed&lt;/li>
&lt;li>Ensure they are unique, based on the id&lt;/li>
&lt;li>Sort them by the publish date&lt;/li>
&lt;li>Output the result&lt;/li>
&lt;/ol>
&lt;p>The end result is one rss feed that contains the unique list of links and is sorted properly. I just then point the
WordPress RSS widget at that feed, and it works.&lt;/p>
&lt;p>You can do a lot more fancy things, but what I’ve described above is the simplest.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Refracted</title><link>https://garethlennox.com/2009/03/04/refracted/</link><pubDate>Wed, 04 Mar 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/03/04/refracted/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/03/04/refracted/">Refracted&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 04 March 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>So I&amp;rsquo;ve decided to start posting my own photo&amp;rsquo;s onto a dedicated photo blog, you may have noticed the photos appearing
in the sidebar (the wonders of rss!).&lt;/p>
&lt;p>If you&amp;rsquo;re interested in photography, you might find it interesting.
The blog&amp;rsquo;s address is &lt;a href="http://refracted.co.za/">http://refracted.co.za/&lt;/a>. I&amp;rsquo;m not going to be posting any more photos on
this blog, other than the ones in the sidebar.&lt;/p>
&lt;h3 id="on-the-name">On the name&lt;/h3>
&lt;p>Its tricky coming up with unique, short names that can be turned into domain names. I came up with
&lt;a href="http://refracted.co.za/">refracted.co.za&lt;/a> the other day, and it seems quite fitting, as when a photograph is created,
the light cannot help but be refracted and bent, firstly by the interface between the glass in the lens elements and the
air (it&amp;rsquo;s related to the speed of light in the different mediums - see
&lt;a href="http://en.wikipedia.org/wiki/Refraction">wikipedia&lt;/a> for more information), and by the lens elements themselves.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>How to sort rated items</title><link>https://garethlennox.com/2009/02/23/how-to-sort-rated-items/</link><pubDate>Mon, 23 Feb 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/02/23/how-to-sort-rated-items/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/02/23/how-to-sort-rated-items/">How to sort rated items&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 23 February 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>&lt;a href="http://www.evanmiller.org/how-not-to-sort-by-average-rating.html">This&lt;/a> is a fascinating article:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>PROBLEM&lt;/strong>: You are a web programmer. You have users. Your users rate stuff on your site. You want to put the
highest-rated stuff at the top and lowest-rated at the bottom. You need some sort of &amp;ldquo;score&amp;rdquo; to sort by.&lt;/p>&lt;/blockquote>
&lt;p>The article goes into detail about how all the most common sorting algorithms are incorrect. We implemented a system a
while back, using wrong solution #2 (from the article), and had all sorts of issues with things getting sorted
incorrectly. The proposed algorithm looks rather scary though.&lt;/p>
&lt;p>Need to keep this in mind when I next implement a rating-based system.&lt;/p>
&lt;p>UPDATE: &lt;a href="http://www.evanmiller.org/rank-hotness-with-newtons-law-of-cooling.html">Another article&lt;/a>, now bringing in a
time component.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Commented out code</title><link>https://garethlennox.com/2009/02/16/commented-out-code/</link><pubDate>Mon, 16 Feb 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/02/16/commented-out-code/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/02/16/commented-out-code/">Commented out code&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 16 February 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>One of my pet peeves is opening a source code file, and seeing half of it commented out, or blocks within it commented
out. What&amp;rsquo;s wrong with this?&lt;/p>
&lt;p>Commented out code serves no purpose, other than to confuse.&lt;/p>
&lt;p>If you try uncomment it, chances are that the code around it has changed, and the uncommented code now won’t even
compile.&lt;/p>
&lt;p>Also, when reading the code and trying to understand it, the chunks of commented out code get in the way. “Should I be
taking this code into account, or not?”&lt;/p>
&lt;p>A lot of the time it is not obvious as to why it is commented out. I’ve seen lots of pieces of code commented out, with
no reason given as to why. Maybe the developer was testing something and forgot to uncomment the code before checking
in? Or is it old code that was not needed any more (then why is it still here?).&lt;/p>
&lt;p>Code is usually commented out when the developer is not sure if the code will be needed in the future, and is leaving it
there “just in case”.&lt;/p>
&lt;p>Ultimately, you don&amp;rsquo;t need to keep commented code around. Your source control system can handle it. As long as you
comment your commit properly, its a matter of 5 minutes work to find the old code and resurrect it.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Ribbons</title><link>https://garethlennox.com/2009/02/16/ribbons/</link><pubDate>Mon, 16 Feb 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/02/16/ribbons/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/02/16/ribbons/">Ribbons&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 16 February 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Took this the other day, just a ribbon hanging off the ceiling.&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2009/ribbons.jpg" alt="Ribbons" />
&lt;/figure>&lt;/div>
&lt;/article></description></item><item><title>Turbulence</title><link>https://garethlennox.com/2009/01/23/turbulence/</link><pubDate>Fri, 23 Jan 2009 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2009/01/23/turbulence/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2009/01/23/turbulence/">Turbulence&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 23 January 2009&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Took this the other day from my flat&amp;rsquo;s balcony.&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2009/turbulence.jpg" alt="Turbulence" />
&lt;/figure>&lt;/div>
&lt;/article></description></item><item><title>Looking Up</title><link>https://garethlennox.com/2008/12/11/looking-up/</link><pubDate>Thu, 11 Dec 2008 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2008/12/11/looking-up/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2008/12/11/looking-up/">Looking Up&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 11 December 2008&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>So, after much thought, I&amp;rsquo;ve decided to start posting more photos here. Hopefully it will force me to post more often!&lt;/p>
&lt;p>This picture was taken on a yacht for an end of year function.&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2008/looking_up.jpg" alt="Looking up" />
&lt;/figure>&lt;/div>
&lt;/article></description></item><item><title>Learning Zend Framework</title><link>https://garethlennox.com/2008/06/16/learning-zend-framework/</link><pubDate>Mon, 16 Jun 2008 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2008/06/16/learning-zend-framework/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2008/06/16/learning-zend-framework/">Learning Zend Framework&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 16 June 2008&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>So, I&amp;rsquo;m playing with &lt;a href="http://framework.zend.com/">Zend Framework&lt;/a>. My initial impressions are that it seems very cool.&lt;/p>
&lt;p>The database stuff especially. One thing, and this is not limited to the Zend Framework, is that it&amp;rsquo;s such a big system,
there is a lot of stuff to get your head around, so documentation is critical. Unfortunately, the documentation is
written on a per-component basis, so it gives you next to no useful information on commonly encountered problems.&lt;/p>
&lt;p>There is a quick start, but it ignores common issues, such as: How do you create a link to another controller (i.e.
another part of the system)?&lt;/p>
&lt;p>Now, I just spent 30 minutes trying to find this out. The official documentation is silent on this basic task. After
searching all over the place, I finally found &lt;a href="http://naneau.nl/2007/07/08/use-the-url-view-helper-please/">this site&lt;/a>,
that tells you to use &amp;ldquo;the url helper&amp;rdquo;. There is nothing (or at least as far as I can see) about this url helper in the
documentation.&lt;/p>
&lt;p>Shouldn&amp;rsquo;t the documentation cover this sort of thing? Or at least a FAQ somewhere? (there is one on the wiki,
&lt;a href="http://framework.zend.com/wiki/display/ZFUSER/Frequently+Encountered+Problems">here&lt;/a>, but its about frequently
encountered problems, not questions, and does not cover the above issue).&lt;/p>
&lt;p>Maybe there is something I&amp;rsquo;m talking about, but if it does exist, its not easy to find on google!&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>The Future of Web Apps summit</title><link>https://garethlennox.com/2006/04/21/the-future-of-web-apps-summit/</link><pubDate>Fri, 21 Apr 2006 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2006/04/21/the-future-of-web-apps-summit/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2006/04/21/the-future-of-web-apps-summit/">The Future of Web Apps summit&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 21 April 2006&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>You want to know what all the big guys are doing out there in the &amp;ldquo;web 2.0&amp;rdquo; world? Have a listen to the mp3s of the
&amp;ldquo;&lt;a href="http://www.carsonworkshops.com/summit/index.html">Future of Web Apps&lt;/a>&amp;rdquo; summit.&lt;/p>
&lt;p>There are guys from
del.icio.us, Flickr, 37Signals, Google, Yahoo and others speaking.&lt;/p>
&lt;p>I have yet to listen to all of them, but the ones I have listened to are top notch.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Editing magic</title><link>https://garethlennox.com/2006/04/04/editing-magic/</link><pubDate>Tue, 04 Apr 2006 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2006/04/04/editing-magic/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2006/04/04/editing-magic/">Editing magic&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 04 April 2006&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>&lt;a href="http://tinymce.moxiecode.com/">TinyMCE&lt;/a> rocks! I have been integrating it into our content management system, and I
must say its impressive.&lt;/p>
&lt;p>Its very easy to use, and Just Works™, unlike some other web rich text editors out there. I managed to build a custom
link screen in a couple of hours, with very little javascript. Another bonus is that it outputs nice valid XHTML, unlike
other editors.&lt;/p>
&lt;p>While using the editor., I have realised that I can write content much faster in our CMS using the default textile
formatting, but people want the rich text editor, and it looks very impressive, so we are gonna give it to them :)&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Hermanus</title><link>https://garethlennox.com/2006/04/02/hermanus/</link><pubDate>Sun, 02 Apr 2006 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2006/04/02/hermanus/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2006/04/02/hermanus/">Hermanus&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 02 April 2006&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Ahhh&amp;hellip;. perfect for skiing! :)&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2006/hermies.jpg" alt="Hermanus, January 2006" />
&lt;/figure>&lt;/div>
&lt;/article></description></item><item><title>Wordpress 2</title><link>https://garethlennox.com/2006/04/02/wordpress-2/</link><pubDate>Sun, 02 Apr 2006 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2006/04/02/wordpress-2/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2006/04/02/wordpress-2/">Wordpress 2&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 02 April 2006&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>This blog is now running under wordpress 2. Its looks very spiffy, but I still need to explore all the changes.&lt;/p>
&lt;p>Once thing I noticed is that you can add categories while you are editing a post (I mentioned it
&lt;a href="https://garethlennox.com/2005/04/22/small-issues-with-wordpress/">here&lt;/a> a while ago).&lt;/p>
&lt;p>I have turned off the WYSIWYG editor for the moment, because there is no functionality to paste code (i.e. html tags)
into the edit box, as it doesn&amp;rsquo;t escape it properly.&lt;/p>
&lt;p>Otherwise, looking good!&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Web based feed-readers</title><link>https://garethlennox.com/2005/12/02/web-based-feed-readers/</link><pubDate>Fri, 02 Dec 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/12/02/web-based-feed-readers/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/12/02/web-based-feed-readers/">Web based feed-readers&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 02 December 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Since I discovered &lt;a href="http://en.wikipedia.org/wiki/RSS_(file_format)">rss feeds&lt;/a>, I have tried many feed readers, but
all the applications didn&amp;rsquo;t work for me, I needed a web-based reader.&lt;/p>
&lt;p>Why? I need to be able to access it from multiple computers, making it difficult to sync read/unread items. A web app
solves this by being accessible from anywhere.&lt;/p>
&lt;p>I ended up settling on &lt;a href="http://bloglines.com/">Bloglines&lt;/a>, and used it for about a year. I have recently switched to
using &lt;a href="http://gregarius.net/">Gregarius&lt;/a>. Its a nifty PHP feed reader that&amp;rsquo;s skinnable and has lots of plugins to
customise it. The user-interface is also much better than Bloglines, and since its skinnable, if you don&amp;rsquo;t like how it
looks, make your own skin!&lt;/p>
&lt;p>Its obviously not a hosted service, so you need some web space, but I much prefer it. Its nice to be in control. :)&lt;/p>
&lt;p>Recommended.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Lack of updates</title><link>https://garethlennox.com/2005/09/10/lack-of-updates/</link><pubDate>Sat, 10 Sep 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/09/10/lack-of-updates/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/09/10/lack-of-updates/">Lack of updates&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 10 September 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Yes, I am still around :)&lt;/p>
&lt;p>We are currently working on a big project for the US market, and are having to put in some substantial overtime.
Hopefully this won&amp;rsquo;t go on for too much longer, but you never know&amp;hellip;&lt;/p>
&lt;p>I should be updating this site more often, but I seem to be just too lazy at the current time to bother writing about
anything. (Note to self: stop being bloody lazy).&lt;/p>
&lt;p>So, here&amp;rsquo;s to me not being so lazy&amp;hellip;&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Learning [insert language here]</title><link>https://garethlennox.com/2005/05/04/learning-insert-language-here/</link><pubDate>Wed, 04 May 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/05/04/learning-insert-language-here/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/05/04/learning-insert-language-here/">Learning [insert language here]&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 04 May 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I was just reading &lt;a href="http://9rules.com/whitespace/learning_css.php">a post over on whitespace&lt;/a>, and it got me thinking
about learning any computer language.&lt;/p>
&lt;p>It is not enough to read a book and do some examples from the book - you actually need to write something substantial in
the language. Granted, it will probably suck, since you would have built it while learning the language. The important
thing to note is that it would have forced you to find out and understand exactly how the language works, how things are
done, and best practices. The next thing you create will probably be better, and so on.&lt;/p>
&lt;p>I am going to use CSS as an example here. Sure, buy that book on CSS, but after reading it, actually go and create a
full site using CSS. It doesn&amp;rsquo;t matter if you need to continually go back and check the book, or the net, or colleagues.
At first it won&amp;rsquo;t be easy, you will be lost, not know what’s going on and generally confused, but if you stick at it,
you will find you pick up an amazing amount of information, just by using the language. Before you know it, you will be
using the language as if you had always used it.&lt;/p>
&lt;p>This is how I learn&amp;rsquo;t all the languages I currently know, usually without a book, just examples on the net, and a will
to learn.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Ajax-enabled user interfaces</title><link>https://garethlennox.com/2005/04/28/ajax-enabled-user-interfaces/</link><pubDate>Thu, 28 Apr 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/04/28/ajax-enabled-user-interfaces/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/04/28/ajax-enabled-user-interfaces/">Ajax-enabled user interfaces&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 28 April 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>There have been lots of people writing about ajax recently, and more importantly about
&lt;a href="http://www.standards-schmandards.com/index.php?2005/03/01/16-ajax-and-accessibility">ajax accessibility&lt;/a>.&lt;/p>
&lt;p>Keeping it simple, I want to focus on what happens when a user has javascript off, or the browser doesn&amp;rsquo;t support the
XMLHttpRequest object. Now this may seem obvious, but your interface should work without javascript enabled. Maybe it
won&amp;rsquo;t be as flashy, or user friendly, but it should work.&lt;/p>
&lt;p>Our content management system (CMS) has a caching functionality to speed up the delivery of pages, and while it clears
the cache when you change any content, there can be a time where you want to force a refresh. Below is the HTML for the
clear cache link.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-html" data-lang="html">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">&amp;lt;&lt;/span>&lt;span style="color:#0550ae">a&lt;/span> &lt;span style="color:#1f2328">onclick&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#0a3069">&amp;#34;ClearCache(); return false;&amp;#34;&lt;/span> &lt;span style="color:#1f2328">href&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#0a3069">&amp;#34;clearcache/&amp;#34;&lt;/span>&lt;span style="color:#1f2328">&amp;gt;&lt;/span> Clear page cache &lt;span style="color:#1f2328">&amp;lt;/&lt;/span>&lt;span style="color:#0550ae">a&lt;/span>&lt;span style="color:#1f2328">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice that if the user has javascript off, none of the `onclick` code will execute, and they will navigate to the
`clearcache` page, which clears the cache and informs them so, after which they can navigate back to the previous
page. If javascript is on though, the functions `ClearCache` is called, which does all the ajax calls back to the
server, which clears the cache, returning a status value. If the status is not an error a messagebox is displayed
informing the user that the cache has been cleared, &lt;strong>without refreshing the page&lt;/strong>.&lt;/p>
&lt;p>Note that there is a `return false;` after the function call, this effectively cancels the click on the link, stopping
the browser from navigating to the clearcache page. An important thing to note is that while the user experience is
different in the two cases, they are both perfectly usable. It will even work in a text-only browser, such as
&lt;a href="http://lynx.isc.org/">Lynx&lt;/a>.&lt;/p>
&lt;p>One way to ensure that there is always some kind of fallback method is to first get your interface working without ajax.
Then you carefully insert the relevant javascript calls.&lt;/p>
&lt;p>You could also go the &lt;a href="http://www.gmail.com/">gmail&lt;/a> route, and have two totally separate interfaces, one for modern
browsers that support ajax, and another plain HTML interface for older browsers, however this is a lot more work, to
support (usually) a small minority of users.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Behold! A design!</title><link>https://garethlennox.com/2005/04/27/behold-a-design/</link><pubDate>Wed, 27 Apr 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/04/27/behold-a-design/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/04/27/behold-a-design/">Behold! A design!&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 27 April 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Woohoo! No default wordpress template to find here any more.&lt;/p>
&lt;p>I finally got around to creating a design for
this web-log. If you find any dodgy looking areas, please let me know via the comments. I am sure I will be tweaking it,
website designs are never finished!&lt;/p>
&lt;p>By the way, the header is derived from a photograph of a rock face on Table Mountain, Cape Town.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>A couple of (small) issues with Wordpress</title><link>https://garethlennox.com/2005/04/22/a-couple-of-small-issues-with-wordpress/</link><pubDate>Fri, 22 Apr 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/04/22/a-couple-of-small-issues-with-wordpress/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/04/22/a-couple-of-small-issues-with-wordpress/">A couple of (small) issues with Wordpress&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 22 April 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Having been using &lt;a href="http://www.wordpress.org/">wordpress&lt;/a> for a little while now, a couple of things bug me.&lt;/p>
&lt;p>Don&amp;rsquo;t get me wrong, it is an amazing tool, and does its job well, but, as always with any software&lt;/p>
&lt;p>product, there are a couple of little niggly things.&lt;/p>
&lt;p>Maybe its possible to do some of the things I mention below, but I cannot see an obvious way. If there is, please let me
know!&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Adding categories from the write post page.&lt;/strong> This is a no-brainer. Currently, to add categories, I have to save my
post, and navigate a couple of pages away to be able to add a category.&lt;/li>
&lt;li>&lt;strong>Intelligent URL transforming.&lt;/strong> Change &lt;code>images/something.png&lt;/code> to something like (in my case)
&lt;code>/g/images/something.png&lt;/code>. This way if my blog moves in the future, all my image links don&amp;rsquo;t break. Admittedly, it is
a small problem, so this one is a nice to have. Not sure if this is possible with the different plugins (I am using
Markdown).&lt;/li>
&lt;/ol>
&lt;p>Thats it at the moment. Two slightly annoying things, both of which have a workaround, so I suppose I will just live
with it. ;)&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Panoramics</title><link>https://garethlennox.com/2005/04/16/panoramics/</link><pubDate>Sat, 16 Apr 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/04/16/panoramics/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/04/16/panoramics/">Panoramics&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 16 April 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>I recently found some useful software that automatically stitches together multiple images to create
panoramics.&lt;/p>
&lt;p>Other panoramic software requires you to manually identify which picture goes where, but
&lt;a href="http://www.cs.ubc.ca/~mbrown/autostitch/autostitch.html">Autostitch&lt;/a> does it all automatically.&lt;/p>
&lt;p>You give it all the images, and it works out what image goes where, adjusting each one so they blend together. It works
suprisingly well.&lt;/p>
&lt;p>As an example, I have stitched together a panoramic I made while in the Cedarberg, during Easter 2005 (click the image
for a larger version).&lt;/p>
&lt;figure class="">
&lt;img src="https://garethlennox.com/posts/2005/cedarburg_stadsaal_easter.jpg" alt="Cedarburg, Stadsaal, Easter 2005" />
&lt;/figure>
&lt;p>I didn&amp;rsquo;t do any tweaking at all, this is the raw output. Pretty impressive stuff.&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>Keeping a session alive</title><link>https://garethlennox.com/2005/04/14/keeping-a-session-alive/</link><pubDate>Thu, 14 Apr 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/04/14/keeping-a-session-alive/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/04/14/keeping-a-session-alive/">Keeping a session alive&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 14 April 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>One of the problems we found with people using our content management system was that, frequently, they would take very
long editing a page, causing the session to time out, thereby losing their changes.&lt;/p>
&lt;p>We could have written code to catch the timout session, and somehow not lose their changes, but we decided on a
different course of action, one that I think is much cleaner.&lt;/p>
&lt;p>I made use of some javascript and &lt;a href="http://www.adaptivepath.com/publications/essays/archives/000385.php">ajax&lt;/a> (aka
XMLHttpRequest) to ping the server every five minutes. On the server I wrote a special page that would just refresh the
session, when requested.&lt;/p>
&lt;p>The code is quite simple, we use the setTimeout javascript method to initiate the ping, and ajax to make the call back
to the server.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-javascript" data-lang="javascript">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">var&lt;/span> &lt;span style="color:#1f2328">timeout&lt;/span>&lt;span style="color:#0550ae">:&lt;/span> &lt;span style="color:#0550ae">300000&lt;/span>&lt;span style="color:#1f2328">;&lt;/span> &lt;span style="color:#57606a">//5 mins
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">&lt;/span>&lt;span style="color:#cf222e">function&lt;/span> &lt;span style="color:#1f2328">pingServer&lt;/span>&lt;span style="color:#1f2328">()&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">http&lt;/span>&lt;span style="color:#0550ae">:&lt;/span> &lt;span style="color:#1f2328">getHTTPObject&lt;/span>&lt;span style="color:#1f2328">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">http&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">open&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;GET&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#0a3069">&amp;#34;http://server/admin/ping/&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#cf222e">false&lt;/span>&lt;span style="color:#1f2328">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">http&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">send&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#cf222e">null&lt;/span>&lt;span style="color:#1f2328">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">setTimeout&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;pingServer()&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">timeout&lt;/span>&lt;span style="color:#1f2328">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">setTimeout&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;pingServer()&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">timeout&lt;/span>&lt;span style="color:#1f2328">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>the setTimeout method takes two arguments, a function name, and a timeout value in milliseconds. The getHTTPObject
function, is defined &lt;a href="http://www.peej.co.uk/articles/rich-user-experience.html">on this blog&lt;/a>.&lt;/p>
&lt;p>Result? The session timeout of 20 minutes is never hit, as long as the user has their browser open. A much better user
experience, I would say!&lt;/p>&lt;/div>
&lt;/article></description></item><item><title>New blog</title><link>https://garethlennox.com/2005/04/14/new-blog/</link><pubDate>Thu, 14 Apr 2005 00:00:00 +0000</pubDate><guid>https://garethlennox.com/2005/04/14/new-blog/</guid><description>&lt;article class="post">
&lt;header>
&lt;h1>
&lt;a href="https://garethlennox.com/2005/04/14/new-blog/">New blog&lt;/a>
&lt;/h1>
&lt;div class="post-meta">
&lt;time> 14 April 2005&lt;/time>
&lt;/div>
&lt;/header>
&lt;div class="content">&lt;p>Welcome to my new blog, we shall see if this lasts&amp;hellip;&lt;/p>
&lt;p>I will be talking about anything that interests me, the industry that I work in, and anything else I want (it is &lt;em>my&lt;/em>
site after all!). I work in the software development industry, developing mostly in C# and &lt;a href="http://www.php.net/">PHP&lt;/a>. I
also design websites, and am a keen supporter of &lt;a href="http://www.webstandards.org/">web standards&lt;/a>.&lt;/p>
&lt;p>I am a part owner and director of &lt;a href="http://dwakn.com/">Dwakn Consulting&lt;/a>, a company a couple of mates and I started after
&lt;a href="http://www.uct.ac.za/">varsity&lt;/a>. We are concentrating on website design and web application development, and have
developed our own content management system (hopefully, I will find some time to reveal some detail about this system).&lt;/p>
&lt;p>This site is hosted on Dwakn&amp;rsquo;s server, and is powered by &lt;a href="http://wordpress.org/">wordpress&lt;/a>.&lt;/p>
&lt;p>Hopefully, this won&amp;rsquo;t be the only post on this site :)&lt;/p>&lt;/div>
&lt;/article></description></item></channel></rss>