<?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/"
	>

<channel>
	<title>Stuart&#039;s Soliloquy to the void &#187; Development</title>
	<atom:link href="http://hstuart.dk/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://hstuart.dk</link>
	<description>A blog on development, baking and the universe.</description>
	<lastBuildDate>Sun, 13 May 2012 21:46:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=0</generator>
		<item>
		<title>Mercurial 2.3 sprint</title>
		<link>http://hstuart.dk/2012/05/13/mercurial-2-3-sprint/</link>
		<comments>http://hstuart.dk/2012/05/13/mercurial-2-3-sprint/#comments</comments>
		<pubDate>Sun, 13 May 2012 21:46:38 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mercurial]]></category>

		<guid isPermaLink="false">http://hstuart.dk/?p=639</guid>
		<description><![CDATA[Just finished the Mercurial 2.3 developer sprint on behalf of the company I work for, Edlund A/S. It was really nice to meet a lot of the familiar faces and the new ones from Facebook and Wolfram Research. It is especially in meetups like these that you truly get to experience the friendliness that&#8217;s part [...]]]></description>
			<content:encoded><![CDATA[<p>Just finished the <a href="http://mercurial.selenic.com/wiki/2.3sprint">Mercurial 2.3 developer sprint</a> on behalf of the company I work for, <a href="http://edlund.dk">Edlund A/S</a>. It was really nice to meet a lot of the familiar faces and the new ones from Facebook and Wolfram Research. It is especially in meetups like these that you truly get to experience the friendliness that&#8217;s part of the people around the Mercurial project.</p>
<p>Some of my more noteworthy contributions around the Mercurial eco-system during the sprint were:</p>
<ul>
<li>Release <a href="https://bitbucket.org/hstuart/repoman">RepoMan</a>, the repository forest manager that we have developed at Edlund A/S for managing a complex multi-repository setup where some modules are individually co-dependent but we want to be able to modify all of them coherently at the same time. We&#8217;re hoping that other people out there will find it useful and/or interesting.</li>
<li>Proof-of-concept, <a href="https://bitbucket.org/hstuart/hg-deadkeys">hg-deadkeys</a>, written with <a href="http://aragost.com/about/employees/martin-geisler/">Martin Geisler</a> from Aragost Trifork, which is an extension for marking changesets ‘dead’ (which includes a slightly hacky misuse of the phases concept) so they aren&#8217;t propagated across the client/server boundary &#8211; requires that the extension is enabled on both client and server. Eventually this should be able to garbage collect changesets (e.g. strip them) that the user considers permanently dead.</li>
<li>Bit more polished proof-of-concept, <a href="https://bitbucket.org/hstuart/hg-multiundo">hg-multiundo</a>, written with <a href="http://jasonfharris.com/">Jason F. Harris</a>, for supporting automatical snapshot-based backups of your repository and working copy state whenever you modify files. The extension allows you to undo/redo in multiple levels the last things you have done in the repository. No more ‘Oh no, I did hg up -C and now all my changes are gone!’ &#8211; they&#8217;re just an ‘hg undo’ away. Disk space performance improvements will probably be introduced later on.</li>
</ul>
<p>Apart from that we had a lot of good discussions on the project and things around it. I&#8217;m looking forward to the next sprint.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2012/05/13/mercurial-2-3-sprint/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>X.509 certificates and Mercurial</title>
		<link>http://hstuart.dk/2010/04/09/x-509-certificates-and-mercurial/</link>
		<comments>http://hstuart.dk/2010/04/09/x-509-certificates-and-mercurial/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 20:48:18 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[distributed version control]]></category>
		<category><![CDATA[Mercurial]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://hstuart.dk/?p=462</guid>
		<description><![CDATA[As one of the primary developers touching certificates in the Mercurial world, I am often asked how they work, what people need to do to use them and how they can work well with Mercurial. A principal thing to remember here is that Mercurial will not work as a complete server out of the box, [...]]]></description>
			<content:encoded><![CDATA[<p>As one of the primary developers touching certificates in the <a href="http://mercurial.selenic.com">Mercurial</a> world, I am often asked how they work, what people need to do to use them and how they can work well with Mercurial.</p>
<p>A principal thing to remember here is that Mercurial will <em>not</em> work as a complete server out of the box, requesting authentication information, in the form of basic, digest, or certificates, at all. This means that in order to use X.509 certificates with Mercurial, one needs to place a web server that knows of these authentication mechanisms in front of it.</p>
<p>This guide is written at the existence of Mercurial version 1.5.1 and touches on many newer features, so if your distribution is old or lacks these features, perhaps it&#8217;s time to upgrade to the latest and greatest.</p>
<h2>X.509 certificates and SSL/TLS</h2>
<p>The most commonly known aspect of X.509 are the certificates. At some level, one can think of a X.509 certificate as having a public and a private key. The public key is the one that secure websites present to you when you, for instance, visit Gmail. You can encrypt data to the intended recipient using this key and only with the corresponding private key can this information be decrypted. In reality, the actual public/private key pair is only used to compute a shared secret, and this is the secret used to communicate securely for the remainder of the conversation.</p>
<p>A X.509 certificate is issued by a certificate authority—some of the commonly known certificate authorities, i.e. that are trusted by a lot of people, can be seen in your browser&#8217;s certificate settings—however, a certificate authority can be anybody <em>you</em> trust, e.g. yourself. This certificate authority can then issue server certificates (that represent a server&#8217;s identity), and client certificates (that represent a client&#8217;s identity). As long as you control the ecosystem of your environment, e.g. you know who your clients are, they know who you are, there is no reason to give out money to some third-party certificate authority, you can accomplish everything you need to on your own.</p>
<p>In order to become your own certificate authority and certificate issuer, you need one of two tools: OpenSSL or makecert.exe, the latter only being available on Windows (there are probably countless other tools as well, to be fair, but I do not cover them here). Below I will cover how to use each of these to set up everything, but before we delve into the details, we will look very briefly at what a certificate authority certificate is, and what ‘normal’ certificates are.</p>
<p><strong>Certificate authority:</strong> A certificate authority is basically just a certificate that has signed itself. If you trust this certificate&#8217;s public key, you will also trust any certificate that has been issued by this certificate authority.</p>
<p><strong>Normal certificates:</strong> A normal certificate is just a certificate that has been signed by a certificate authority (or in reality a certificate authority or an intermediate certificate—you can have a full chain of certificates signing each other if needed).</p>
<p>Now, there are a lot of weird details in these certificates. You may hear terms thrown around such as OU (Organisational Units) and whatnot. The only important part for our purposes is the CN (Common Name). This is the name of the certificate holder, e.g. the server&#8217;s name, or the user&#8217;s name. So if you access your server as ‘<em>hg.my.cool.server</em>’, your server certificate&#8217;s CN must be ‘hg.my.cool.server’.</p>
<h3>OpenSSL</h3>
<p>Like everything else in the X.509 certificate landscape, OpenSSL has <em>a lot</em> of options, switches and strange voodoo attached to it. Lest this post be turned into a really boring tutorial on certificates, I will just give a few very cursory examples of how you can generate the different certificates. There are plenty of different tutorials on this topic already. Note that Microsoft&#8217;s IIS is a tad weird in how exactly it requires the certificate to be constructed, so we will not cover this for OpenSSL, but only for makecert.exe (inquiring minds can figure out all the details of generating certificate requests and processing these in OpenSSL if they prefer).</p>
<ul>
<li>
<p><strong>Certificate authority:</strong> <code>openssl req -x509 -nodes -days 365 -subj '/CN=MyCA' -newkey rsa:1024 -keyout ca.key -out ca.pem</code></p>
<p>The ‘MyCA’ part specifies the name of your certificate authority, so you will probably want to name it something a bit more descriptive.</p>
<p>This gives us a certificate authority certificate with a private key stored in <code>ca.key</code> and the public certificate in <code>ca.pem</code>. You will need both of these to issue other certificates. Also, if you do not want to get scary pop-ups with invalid certificate trust models in your browser when you browse the hg repositories through hgweb, you will need to install <code>ca.pem</code> into the trusted root certificate authorities in your browsers.</p>
</li>
<li><strong>Normal certificates:</strong>
<ul>
<li>
<p><strong>Generate request for signing:</strong> <code>openssl req -new -nodes -out <em>name</em>-req.pem -keyout <em>name</em>.key -subj '/CN=<em>name</em>'</code></p>
<p>You should, of course, replace <em>name</em> with something more sensible, e.g. your server&#8217;s fully qualified domain name (the one people will be entering in their browser to visit it).</p>
</li>
<li><strong>Signing the request:</strong> <code>openssl x509 -req -in <em>name</em>-req.pem -CA ca.pem -CAkey ca.key -out <em>name</em>.pem -CAcreateserial</code></li>
</ul>
<p>Do note that this is the quick-and-dirty way of generating certificates for use in testing/simpler controlled production scenarios. There are a lot more advanced features (like <code>openssl ca</code>) that will allow you to act more like a real certificate authority. If you need these things, go look up some OpenSSL tutorials, then come back here to see how things work with Mercurial.</p>
<p>The final issue is getting these certificates into a form that your browser will like. They require the certificate to be in a special format, e.g. PKCS#12. To get that we use the <code>openssl</code> tool again like this: <code>openssl pkcs12 -export -in <em>name</em>.pem -inkey <em>name</em>.key -out <em>name</em>.pfx</code>. This file can be imported into your browser in a fitting place.</p>
</li>
</ul>
<h3>makecert.exe</h3>
<p><code>makecert.exe</code> is a bit of a different beast from <code>openssl</code> as it interfaces directly with the machine&#8217;s or user&#8217;s certificate store (the special place where certificates live a happy life in Windows).</p>
<ul>
<li>
<p><strong>Certificate authority:</strong> <code>makecert.exe -pe -r -ss My -m 12 -n "CN=MyCA"</code></p>
<p>This will install the root certificate into the current user&#8217;s personal certificate store and mark the private key exportable. To see the current user&#8217;s certificate store, run <code>certmgr.msc</code>.</p>
<p>The certificate&#8217;s public key will need to be exported and subsequently imported into the ‘Trusted Root Certification Authorities’ on each machine that trusts this certificate to issue other certificates.</p>
</li>
<li>
<p><strong>Server certificate:</strong> <code>makecert.exe -pe -is My -in "MyCA" -n "CN=<em>name</em>" -sky exchange -ss My -sr LocalMachine -m 12 -eku 1.3.6.1.5.5.7.3.1 -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12</code></p>
<p>Do note that this certificate is imported into the local machine&#8217;s personal certificate store—this is where IIS expects to find server certificates. To see these certificates, start <code>mmc</code> manually and add the certificate snap-in.</p>
</li>
<li><strong>Client certificate:</strong> <code>makecert.exe -pe -is My -in "MyCA" -n "CN=<em>name</em>" -sky exchange -ss My -m 12 -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12</code></li>
</ul>
<p>If the client and server certificates aren&#8217;t generated on the machines you need them on, you need to select the certificate in the management snap-in and export it, including the private key. Exporting as PKCS#12 is usually the safest bet.</p>
<p>This should basically cover how we get the actual certificates. Now, to use them.</p>
<h2>Configuring a web server to use certificates</h2>
<p>There are countless web servers and operating systems to run them on. I will give a <em>very</em> brief guide to running it on two of the most archetypical web server/operating system combinations: Apache 2.2 on Linux (Ubuntu), and IIS7 on Windows Server 2008. In particular, I will assume that you have already got Mercurial running and working just fine on both web servers.</p>
<h3>Apache 2.2 on Linux (Ubuntu)</h3>
<p>Setting up apache with mod_ssl can be done in a multitude of ways, I&#8217;ll just presume you have enabled mod_ssl already and show how to create a really, really skeleton version of a SSL site that serves Mercurial repositories. We will set up a server that serves a few Mercurial repositories using hgwebdir, from the root of the website, and we&#8217;ll only define a virtual host for listening on port 443.</p>
<h4>Server certificates</h4>
<p>The main configuration is as follows:</p>
<pre>
&lt;VirtualHost *:443&gt;
  SSLEngine on
  SSLCertificateFile /path/to/<em>myserver</em>.pem
  SSLCertificateKeyFile /path/to/<em>myserver</em>.key
  SSLCACertificateFile /path/to/ca.pem
  SSLCACertificatePath /path/to

  ScriptAliasMatch ^(.*) /path/to/hgwebdir.cgi$1
&lt;/VirtualHost&gt;
</pre>
<p>Do note that if you have cloned the Mercurial repository, you should copy <code>hgwebdir.cgi</code> to a different location and make it executable. Furthermore, see <a href="http://mercurial.selenic.com/wiki/HgWebDirStepByStep">HgWebDirStepByStep</a> for further instructions.</p>
<p>This simple solution serves our self-issued server certificate when we access our website using TLS/SSL.</p>
<h4>Client certificates</h4>
<p>Client certificates do not require much more than that:</p>
<pre>
&lt;VirtualHost *:443&gt;
  SSLEngine on
  SSLCertificateFile /path/to/<em>myserver</em>.pem
  SSLCertificateKeyFile /path/to/<em>myserver</em>.key
  SSLCACertificateFile /path/to/ca.pem
  SSLCACertificatePath /path/to
  SSLVerifyClient require

  ScriptAliasMatch ^(.*) /path/to/hgwebdir.cgi$1
&lt;/VirtualHost&gt;
</pre>
<p>This allows anyone with a validating certificate to connect, but no other checks are made. In order to restrict which certificates can be used to connect to the server, we can use the built-in fake authentication mechanism of mod_ssl&#8217;s.</p>
<pre>
&lt;VirtualHost *:443&gt;
  SSLEngine on
  SSLCertificateFile /path/to/<em>myserver</em>.pem
  SSLCertificateKeyFile /path/to/<em>myserver</em>.key
  SSLCACertificateFile /path/to/ca.pem
  SSLCACertificatePath /path/to
  SSLVerifyClient require

  &lt;Location /&gt;
    SSLRequireSSL
    SSLOptions +FakeBasicAuth
    AuthName "FakeBasicAuth"
    AuthType Basic
    AuthUserFile /path/to/httpd.passwd
    require valid-user
  &lt;/Location&gt;

  ScriptAliasMatch ^(.*) /path/to/hgwebdir.cgi$1
&lt;/VirtualHost&gt;
</pre>
<p>The fake basic auth basically means that we will create a file, <code>httpd.passwd</code> that contains the certificate subjects as usernames and <code>password</code> in its hashed form as password. Then mod_ssl takes care of verifying that the certificate is in this file before allowing it to access the remote location. To get the certificate subject to use as username, you can use <code>openssl</code> to get it: <code>openssl x509 -subject -in <em>name</em>.pem</code>. So for our simple client certificate example above, we would have a <code>httpd.passwd</code> file with the following contents:</p>
<pre>
/CN=<em>name</em>:xxj31ZMTZzkVA
</pre>
<p>The <code>xxj31ZMTZzkVA</code> part is <code>password</code> that has been hashed. Usually, if you&#8217;ve bought your certificate from a real certificate authority, your certificate will also contain country, organisation, and a host of other fancy things. You can also get these by embellishing the subject when you generate the certificate request, thus a real ‘username’ for a certificate might be <code>/C=US/O=My fancy company/OU=West coast offices/CN=John Doe</code>, but for our simple explanation purposes they merely detract from the message.</p>
<p>This is all it takes to set up client certificate authentication and authorization on Apache.</p>
<h3>Internet Information Server 7 (Windows Server 2008)</h3>
<h4>Server certificates</h4>
<p>The server certificate part is easy. Make sure the certificate is installed in the local machine&#8217;s personal certificate store, then add a HTTPS-binding to the site you want to host and select the relevant certificate in the drop-down list. That&#8217;s it.</p>
<h4>Client certificates</h4>
<p>Under SSL settings, set that the site requires SSL and that client certificates are required (few systems really work well with the optional part). This is the easy part. The hard part is that after IIS6, Microsoft has decided to drop the interface management UI for mapping certificates to Windows accounts completely, so we will have to do all this in an XML configuration file, and change some system XML-files and whatnot to get everything working.</p>
<p>The first file we need to edit is <code>%SystemRoot%\system32\inetsrv\config\applicationHost.config</code> where we need to find a line like this: <code>&lt;section name=&quot;iisClientCertificateMappingAuthentication&quot; overrideModeDefault=&quot;Deny&quot;&gt;</code> and change the <code>Deny</code> to <code>Allow</code>. This will allow us to configure this setting in the root of each website that your server is hosting. (If you have users who have write access to the file system, then they will also be able to override the setting for their virtual directories; it is up to you to figure out whether this poses a security risk for you).</p>
<p>In the root directory of your website, edit (or create) the file <code>web.config</code> that we can use to configure IIS7 (and ASP.NET for that matter, but that&#8217;s probably not terribly relevant here). For each user we want to grant access we want the certificate&#8217;s public key in PEM-encoded format (that is Base-64 in Microsoft parlance), formatted as a single string (i.e., you remove the newlines from the text-file and copy-paste the contents of the certificate, excluding the first and last line with the dashes). Below is a brief snippet that illustrates this:</p>
<pre>
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;configuration&gt;
  &lt;system.webServer&gt;
    &lt;security&gt;
      &lt;authentication&gt;
        &lt;iisClientCertificateMappingAuthentication enabled=&quot;true&quot;
            oneToOneCertificateMappingsEnabled=&quot;true&quot;&gt;
          &lt;oneToOneMappings&gt;
            &lt;add userName=&quot;testuser1&quot; password=&quot;test&quot; certificate=&quot;<em>CERTIFICATE_STRING</em>&quot; /&gt;
          &lt;/oneToOneMappings&gt;
        &lt;/iisClientCertificateMappingAuthentication&gt;
      &lt;/authentication&gt;
    &lt;/security&gt;
  &lt;/system.webServer&gt;
&lt;/configuration&gt;
</pre>
<p>Now we have told IIS that the user with the certificate <em>CERTIFICATE_STRING</em> logs in as the user <code>testuser1</code> using the password <code>test</code>. However, even though we&#8217;ve set the website to require the use of client certificates, anyone presenting an arbitrary certificate can log in, since anonymous access is enabled. To turn this off, and only allow access for the specified users in the authentication section, we will need to modify the authorization rules as well as the authentication rules to disallow anonymous users. Below the <code>/authentication</code> line in the above configuration we add the following:</p>
<pre>
&lt;authorization&gt;
  &lt;remove users=&quot;*&quot; roles=&quot;&quot; verbs=&quot;&quot; /&gt;
  &lt;add accessType=&quot;Allow&quot; users=&quot;testuser1&quot; /&gt;
&lt;/authorization&gt;
</pre>
<p>Unlike the certificate mapping, this can also be handled from inside the IIS configuration manager under authorization. Now, only <code>testuser1</code> can log on to the site, using his client certificate. In general, you probably want some more users to be able to access your site, so you can go right ahead and add those as well.</p>
<h2>Mercurial and X.509 certificates</h2>
<p>All this, finally, brings us to how Mercurial interacts with certificates. There are, indeed, several things we need to cover here: how to use server certificates with ‘hg serve’ (the built-in web server), accessing a web server that requires client certificates from the Mercurial client, and how we can use the usual access control methods in Mercurial together with client certificates.</p>
<h3>The built-in server, hg serve</h3>
<p><strong>Note:</strong> For hg serve to use SSL, you must have installed pyopenssl.</p>
<p>hg serve supports a <code>--certificate</code> option where you can specify a certificate file for a certificate that verifies. This detail is important, as right now, with the commands we issued above, we have a certificate file, we have a certificate authority file, and we have a private key file. We need to combine all these into a single file with this command: <code>cat <em>name</em>.key <em>name</em>.pem ca.pem > hgserver.pem</code>. If you have a certificate from a known certificate authority, you do not need to combine the certificate authority certificate into your certificate file.</p>
<p>To use this, you now simply just write <code>hg serve --certificate hgserver.pem</code> and you can access your stand-alone server using HTTPS.</p>
<h3>Accessing a web server that requires client certificates</h3>
<p>This is, of course, the really interesting part where everything comes together. In order to use client certificates you need them split up into two different files: <em>name</em>.pem and <em>name</em>.key (if you have followed the guide above for OpenSSL, you already have these two files, otherwise you need to generate them). Now we need to set up an <code>auth</code> section in our local hgrc file:</p>
<pre>
[auth]
something.prefix = my.server.tld
something.cert = <em>name</em>.pem
something.key = <em>name</em>.key
</pre>
<p>When you try to clone, push, pull, incoming, outgoing to <code>my.server.tld</code> (or any path below that), we will automatically send along the specified certificate file and decrypt stuff using the key file. Also note that the <code>something</code> can really be anything, as long as they are connected. That is, if you have two different client certificates for two different servers you could do something like this:</p>
<pre>
[auth]
something.prefix = my.server.tld
something.cert = <em>name</em>.pem
something.key = <em>name</em>.key

somethingelse.prefix = my.other.server.tld
somethingelse.cert = <em>othername</em>.pem
somethingelse.key = <em>othername</em>.key
</pre>
<p>Be aware that the paths to the certificate and keyfile should be absolute (otherwise they&#8217;re read relative to your current working directory).</p>
<p>There is currently no way to discern that certificates are included in the request or not (other than the request possibly failing). Also, the error messages that are given back if there are problems with certificates are less than stellar, but that is, unfortunately, the par for OpenSSL (which Mercurial uses by way of Python).</p>
<h3>Access control using certificate users</h3>
<p>Mercurial contains a number of mechanisms for controlling who can read/push from/to a specific repository. Furthermore, there are extensions such as the acl extension that allows you more fine-grained access control on who may push what files. The usernames that you can specify are delimited with either a space or a comma. See the problem?</p>
<p>A very common certificate username for Apache might be ‘<em>/C=US/S=CA/O=ACME, Inc./OU=Coyote Solutions/CN=John Doe</em>’. This will be parsed as allowing/denying access to the users ‘<em>/C=US/S=CA/O=ACME</em>’, ‘<em>Inc./OU=Coyote</em>’, ‘<em>Solutions/CN=John</em>’, and ‘<em>Doe</em>’. In short, you cannot use these mechanisms with Apache and client certificates right now (this should, of course, be rectified in the Mercurial source code somehow).</p>
<p>With IIS we have no such problem as we have mapped the client certificates to actual Windows account names, and we must just limit based on the Windows account names.</p>
<h3>Verifying the server identity</h3>
<p>The default for Mercurial (or any Python application for that matter), is to connect to a SSL/TLS server <em>and not check that we actually trust the certificate being served</em>. In fact, it is only possible to make Python do this from Python 2.6 and onward, and <em>only</em> if you specify special flags and special files to some of the SSL/TLS calls. Some kind developer who shall remain unnamed has added the necessary support to Mercurial so that we from Python 2.6 can actually verify the remote party. This is done by specifying a certificate trust file in your hgrc file in the web section:</p>
<pre>
[web]
cacerts = /path/to/cacerts.pem
</pre>
<p>This file should contain a list of the certificate authority certificates (PEM encoded), one after the other. If you&#8217;re already on a system that has OpenSSL installed, e.g. most GNU/Linux systems, this can be found in the file <em>/etc/ssl/certs/ca-certificates.crt</em> (or wherever your distribution places it). If not, then you will have to construct this file manually.</p>
<p>If verification fails, you will, again, get some cryptic OpenSSL error message.</p>
<h2>Conclusion/Summary</h2>
<p>These are all the many fancy ways that Mercurial can work together with certificates currently. Some of the ways are cumbersome, but they are hopefully not cumbersome due to Mercurial. We have tried to make them as easy to use as possible (if it can be said that certificates are easy to work with). It is also worth noting that prior to Python 2.6.4 (I believe), it is not possible to use client certificates with Mercurial, if you are also using a HTTP proxy server.</p>
<p>I will try to update this post if/when changes occur to the client and server certificate support in Mercurial. If you have suggestions or issues with using these, please file them on the <a href="http://mercurial.selenic.com/bts">Mercurial issue tracker</a>, thanks!</p>
<p><b>Update:</b> Thanks to Claudio for some useful comments and corrections.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2010/04/09/x-509-certificates-and-mercurial/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Managing online development communities</title>
		<link>http://hstuart.dk/2009/06/15/managing-online-development-communities/</link>
		<comments>http://hstuart.dk/2009/06/15/managing-online-development-communities/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 16:32:28 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://192.168.0.8/?p=414</guid>
		<description><![CDATA[A few friendly reminders to people shepherding development efforts: Strike a cordial tone and do not tell people they do not understand the code. Doing this repeatedly to frequent contributors is even more silly. Do not ignore contributions.It&#8217;s ok if you are busy, but indicate that by replying to the patch, do not ignore it [...]]]></description>
			<content:encoded><![CDATA[<p>A few friendly reminders to people shepherding development efforts:</p>
<ul>
<li><em>Strike a cordial tone and do not tell people they do not understand the code.</em><br /> Doing this repeatedly to frequent contributors is even more silly.</li>
<li><em>Do not ignore contributions.</em><br />It&#8217;s ok if you are busy, but indicate that by replying to the patch, do not ignore it completely.</li>
<li><em>If someone takes the time to go over your bug tracker and fix multiple issues, do not ignore the patches.</em><br />See above.</li>
<li><em>If someone tells you that there are issues in your use of transactions, do consider it an option.</em><br />Transactional safety is hard, it&#8217;s likely that details might have been overlooked.</li>
<li><em>Find a decent working process for reviewing contributions.</em><br />Requiring contributors to bug you until you magnanimously take a look at the contributions gets very tiresome quickly and lessens the odds that said contributor will keep contributing.</li>
<li><em>Give constructive feedback.</em><br />Stating ‘This sucks, but I don&#8217;t have time to explain right now.’ helps no-one but your own ego. A better approach, in case you really do not have the time, would be to write, ‘I have some concerns over the implementation that I would like to voice. I am, however, travelling for the remainder of the week and will try to reply early next week’.</li>
</ul>
<p>That is all.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2009/06/15/managing-online-development-communities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Covariance and design principles</title>
		<link>http://hstuart.dk/2007/10/18/covariance-and-design-principles/</link>
		<comments>http://hstuart.dk/2007/10/18/covariance-and-design-principles/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 09:59:29 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[covariance]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[programming language design]]></category>
		<category><![CDATA[subtyping]]></category>

		<guid isPermaLink="false">http://localhost/?p=140</guid>
		<description><![CDATA[As promised in the last blog post, it is time to get down and dirty with technical facts. Or said in another way, it is time to look at: ‘Why C# let me down’ (you may imagine the blood dripping from the italicised letters). As the title may lead you to believe, the let-down has [...]]]></description>
			<content:encoded><![CDATA[<p>As promised in <a href="http://hstuart.dk/view.hspx?bid=1&amp;id=6">the last blog post</a>, it is time to get down and dirty with technical facts. Or said in another way, it is time to look at: <em>‘Why C# let me down’</em> (you may imagine the blood dripping from the italicised letters). As the title may lead you to believe, the let-down has a lot to do with covariant types, but what are covariant types anyway? Why do they matter? And then how come C# does not have them?</p>
<p>The basic principles of object-oriented languages builds on what in type theory is known as subtyping relationships that are typically expressed <em>σ &lt;: τ</em>, meaning that σ is a subtype of τ. Or expressed in a typical C# manner:</p>
<pre><span class="keyword">public</span> <span class="keyword">class</span> τ {}

<span class="keyword">public</span> <span class="keyword">class</span> σ : τ {}
</pre>
<p>So in other words, we have the property that σ inherits from τ, or that σ is a subtype of τ. It is typical of most object-oriented programs (sorry, most well-written object-oriented programs) to allow you to use the type σ in place of the type τ anywhere in the program and still have a correct program. This is what is typically called Liskov&#8217;s substitution principle, which can be formulated like this: <em>x : τ ⊢ q(x) ∧ σ &lt;: τ ⇒ y : σ ⊢ q(y)</em>. So that is fairly densely looking and what does it really mean? Basically it says: if q(x) is some property that holds on an object x of type τ and if σ is a subtype of τ then if y is an object of type σ then q(y) must also hold. Or in layman&#8217;s terms: it must be possible to use a child class instance everywhere a child&#8217;s class ancestor is expected, without changes to the program, maintaining correctness of the program. So that is probably a pretty good property to go looking for.</p>
<p>Now, before everything gets lost in theory, let us take a look at the actual problem in C#, using an illustrating example:</p>
<pre><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> RandomNumberGenerator {
  <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">double</span> NextValue();
}

<span class="keyword">public</span> <span class="keyword">class</span> DiceResultGenerator : RandomNumberGenerator {
  <span class="keyword">public</span> DiceResultGenerator(<span class="keyword">int</span> rolls, <span class="keyword">int</span> sides) {
    rolls_ = rolls;
    sides_ = sides;
  }

  <span class="keyword">override</span> <span class="keyword">public</span> <span class="keyword">double</span> NextValue() {
    ...
  }

  <span class="keyword">private</span> <span class="keyword">int</span> rolls_, sides_;
}
</pre>
<p>Okay, so this code is a sensible implementation of some random number generator and a dice roller&#8230; or is it? When was the last time you got floating point results from rolling a die? Let us fix that up right here and now by changing the <code><span class="keyword">double</span></code> in the DiceResultGenerator to an <code><span class="keyword">int</span></code>. This is a safe operation since <code><span class="keyword">int</span></code> &lt;: <code><span class="keyword">double</span></code> (and because Liskov&#8217;s substitution principle otherwise applies here—every time you expect a <code><span class="keyword">double</span></code> you can safely use an <code><span class="keyword">int</span></code> in its place). Ignoring floating point representations and byte sizes this typically holds in most object-oriented languages since the integers are contained in the real numbers. So what happens if we compile the modified source code with the Mono C# compiler (the Microsoft one will give a comparable result)?</p>
<pre>`DiceResultGenerator.NextValue()': return type must be `double' to match overridden member `RandomNumberGenerator.NextValue()'</pre>
<p>Bummer, we have not got covariance in method return types. This means that whenever we use a DiceResultGenerator, we <em>must</em> get a <code><span class="keyword">double</span></code> out of it, rather than a <code><span class="keyword">int</span></code>, and we will subsequently have to cast it to an <code><span class="keyword">int</span></code>. All this just because the DiceResultGenerator is part of a sensible inheritance hierarchy for different means to obtain random numbers and that most random numbers are floating point values. That is just plain depressing.</p>
<p>So this is exactly what a covariant return type is: when a child class wants to return a subtype of what the overridden function of the ancestor class returns. And it does not work in C#. Of course, it works in C++, but there are so many other things that annoy me with that language.</p>
<p>C# why did you let me down so?! Oh well, it must be time to find the next language I might actually like.</p>
<p><b>Edit:</b> Astute readers found out that I had switched the subtype relation around in the definition of Liskov&#8217;s substitution principle. Sorry.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2007/10/18/covariance-and-design-principles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>X-Chat 2 Plugins</title>
		<link>http://hstuart.dk/2005/11/29/x-chat-2-plugins/</link>
		<comments>http://hstuart.dk/2005/11/29/x-chat-2-plugins/#comments</comments>
		<pubDate>Tue, 29 Nov 2005 22:53:53 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[IRC]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://localhost/?p=167</guid>
		<description><![CDATA[X-Chat 2 for Windows had its binary download changed from a free download to a shareware download with a 30 day limit a while ago. This was considered by many as a really bad idea. People thought the idea so mind-bogglingly stupid that they created their own free alternate builds without a trial period. This [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.xchat.org/windows/">X-Chat 2 for Windows</a> had its binary download changed from a free download to a shareware download with a 30 day limit a while ago. This was considered by many as a really bad idea. People thought the idea so mind-bogglingly stupid that they created their own free <a href="http://www.silverex.info">alternate builds</a> without a trial period. This post is not about the thing that makes a lot of people feel like feeding the X-Chat 2 for Windows maintainer to the Ravenous Bugblatter Beast of Traal. No, not at all. What this post is about, however, is writing plugins for this IRC client. No, that&#8217;s not what it&#8217;s about either, let me try again. What this post is about, is my mind-bogglingly useless plugin for this IRC client. Yes, that&#8217;s better.
</p>
<p>The plugin I have created is for controlling Winamp from X-Chat 2. Normal plugins for X-Chat 2 are made in C, but I have made a plugin in C++. The source code will illustrate both how to integrate with X-Chat 2 and Winamp using C++.</p>
<p>The plugin will not auto-display what you&#8217;re listening to whenever a song in winamp changes, since I find that annoying. In fact this plugin will do nothing at all unless you ask it to. The plugin&#8217;s functionality is bound to the WIA command, so to see the help for this thing, just go /help wia. The rest should be fairly self-evident.</p>
<p>I have only tested it on the alternate build I&#8217;ve listed above. If it does not work on other builds then try to compile the source on your own. I will <em>not</em> help you with problems with the source, compiling it, your social problems or anything else even remotely related to my X-Chat 2 plugin for controlling Winamp. (You get to figure out how your social problems may or may not be related to that on your own). The plugin is released under the GPL and standard disclaimers are in effect and all that stuff that keeps kind people from sucking (sorry, suing) every last penny out of me. (Not that we have pennies here, but figuratively speaking).</p>
<p>I hope someone, somewhere, sometime, might have some use for this. I haven&#8217;t added it to the official plugin repository for a reason. Please, don&#8217;t post my plugin there.</p>
<p>
<a href="/files/xcwinampx-bin.zip">Binary files (.zip)</a> &#8211; 31.4 kB<br />
<a href="/files/xcwinampx-src.zip">Source files (.zip)</a> &#8211; 26.8 kB</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2005/11/29/x-chat-2-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WSE, DIME, certificates and large attachments</title>
		<link>http://hstuart.dk/2005/10/16/wse-dime-certificates-and-large-attachments/</link>
		<comments>http://hstuart.dk/2005/10/16/wse-dime-certificates-and-large-attachments/#comments</comments>
		<pubDate>Sun, 16 Oct 2005 17:46:58 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://localhost/?p=169</guid>
		<description><![CDATA[Sometimes technology isn&#8217;t really transparent enough, even for us developers. When you do web development with IIS, WSE and ASP.NET you might consider it fairly straightforward to create a webservice that accepts file uploads. I thought so, so off I went coding. Everything went well, the files were being uploaded. Time to test this on [...]]]></description>
			<content:encoded><![CDATA[<p>
Sometimes technology isn&#8217;t really transparent enough, even for us developers. When you do web development with <a href="http://go.microsoft.com/fwlink/?LinkId=7001">IIS</a>, <a href="http://msdn.microsoft.com/webservices/building/wse/default.aspx">WSE</a> and <a href="http://asp.net/">ASP.NET</a> you might consider it fairly straightforward to create a webservice that accepts file uploads. I thought so, so off I went coding. Everything went well, the files were being uploaded. Time to test this on production data: <span style="font-weight: bold;">400 Bad Request</span>. Hmm.
</p>
<p>Of course, prior to this I have already modified web.config to up the max request length like this:</p>
<pre class="code">&lt;<span class="identifier">httpRuntime</span> <span class="identifier">maxRequestLength</span>=<span class="string">"40000"</span> /&gt;
</pre>
<p>So why is it refusing files with an error 400 as soon as they go beyond about 4096KB? Well, it&#8217;s obvious, WSE has a built in limit that you must change as well! (In case my sarcasm isn&#8217;t showing, it was there. Trust me.)</p>
<pre class="code">&lt;<span class="identifier">microsoft</span>.<span class="identifier">web</span>.<span class="identifier">services2</span>&gt;
  &lt;<span class="identifier">messaging</span>&gt;
    &lt;<span class="identifier">maxRequestLength</span>&gt;<span class="number">1024</span>&lt;/<span class="identifier">maxRequestLength</span>&gt;

  &lt;/<span class="identifier">messaging</span>&gt;
&lt;/<span class="identifier">microsoft</span>.<span class="identifier">web</span>.<span class="identifier">services2</span>&gt;
</pre>
<p>This example is taken directly from the <a href="http://msdn.microsoft.com/library/?url=/library/en-us/wse/html/f991ad3d-f574-4085-8a61-98326ff206ed.asp">WSE documentation</a> for the maxRequestLength. Also, you must remember to add the configuration section extension definition for WSE as well &#8211; see the documentation link for how to do this.</p>
<p>
Of course, the story doesn&#8217;t end here. That would be too easy, because the file upload still has a tendency to fail. Hmm. What if we try to sync the value between httpRuntime&#8217;s maxRequestLength and WSE2&#8242;s maxRequestLength? Bonus! So, knowing that these two have to be identical for everything to go well it seems a bit&#8230; ridiculous to have to require the WSE2 field instead of WSE2 just using the httpRuntime value for the maximum request length. I&#8217;m sure there&#8217;s a brilliant reason for not doing this, however, that someone at Microsoft may know, but one could at least have it be equal to httpRuntime&#8217;s maxRequestLength, no? pretty please? Ah well. I&#8217;m sure I&#8217;m not the last to run into this <q>problem</q>.
</p>
<p>
So, now we have taken care of large attachments. Let&#8217;s add a bit of security so we can safely validate the sender of these large attachments. Stage left enter X.509 and SSL certificates. Stage right enter more troubles, a lot more troubles. So let&#8217;s look at a fresh start of IIS and the client, let&#8217;s upload a big file, let&#8217;s say 20 MB: <span style="font-weight: bold;">413: Request Entity too Large</span>. I will have to be frank, this surprised me. How can the request be too large on HTTPS with client certificates when it isn&#8217;t too large on HTTPS without client certificates or on HTTP?
</p>
<p>
My science background teaches me to experiment in this case, so let&#8217;s try it first with a small attachment, say 4 KB, and then let&#8217;s try it with a big attachment, say 20 MB: <span style="font-weight: bold;">200 OK</span>. Hmm. Not only does this seem to indicate a bug in IIS6 (which was the IIS I was working against), but it seems to indicate that there is some non-trivial state sharing going on between disparate connects from the same client. Unfortunately I haven&#8217;t had time to work more on this problem, but if I ever get around to fixing it I&#8217;ll make an update about it. For now I have just created a system that takes a temporary &#8220;session&#8221; variable that is fetched using a certificate call and then the file is uploading using this without certificate. Seems to work.</p>
<p>Gotta love obvious, transparent technology.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2005/10/16/wse-dime-certificates-and-large-attachments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C#, VB and LINQ</title>
		<link>http://hstuart.dk/2005/09/30/c-vb-and-linq/</link>
		<comments>http://hstuart.dk/2005/09/30/c-vb-and-linq/#comments</comments>
		<pubDate>Fri, 30 Sep 2005 16:12:37 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[university]]></category>

		<guid isPermaLink="false">http://localhost/?p=170</guid>
		<description><![CDATA[I went to a colloquium on LINQ (I guess this link might die in the future when the future is no longer the future, so to speak) presented by Erik Meijer who is a technical lead in the WebData group (whatever they do). Meijer is a very charismatic speaker and it was a very good [...]]]></description>
			<content:encoded><![CDATA[<p>I went to a colloquium on <a href="http://msdn.microsoft.com/netframework/future/linq/">LINQ</a> (I guess this link might die in the future when the future is no longer the future, so to speak) presented by <a href="http://research.microsoft.com/%7Eemeijer/">Erik Meijer</a> who is a technical lead in the WebData group (whatever they do). Meijer is a very charismatic speaker and it was a very good presentation he did (although Virtual PC on his laptop couldn&#8217;t entirely keep up). For the uninitiated LINQ stands for Language INtegrated Query and it brings set relational functionality to .NET. VB9 and C#3 will have syntactic sugar for it, other languages can consume it using the assemblies.</p>
<p>LINQ correspond to Haskell&#8217;s monad comprehensions, in case you know what those are, and I think it will be interesting to see how people put it to use, but I could fear that it will create a tendency to put even more data-layer specific code into the business aspects of application. The added expressitivity, however, seems like a great thing and I look forward to play with it.</p>
<p>Meijer also presented a couple of the new things coming in VB9, among these is late-late binding, which allows you to try to access fields on a type Object regardless of whether you know they exist at compile-time or not, so in some sense VB9 is now a complete bastardisation between statically and dynamically typed languages and you get to be able to do some truly nasty things:</p>
<pre class="code">  <span class="keyword">Dim</span> <span class="identifier">z</span> <span class="keyword">As</span> <span class="keyword">Object</span> = {Name := <span class="string">"Test"</span>, ID := <span class="number">20</span>}
  Console.WriteLine(z.(Console.ReadLine()))
</pre>
<p>This allows you to specify the field in the anonymous struct to access at runtime, no more static typing, there be monsters here! What does this mean for Visual Basic programmers? I would guess that the group of programmers that are currently programming Visual Basic aren&#8217;t exactly, in general, those who know what type erasure, type inference and monad comprehensions mean. I wonder whether Microsoft may be letting their developer base <q>walk the plank</q> in some sense, but only time can tell.</p>
<p>Erik Meijer has been teaching as an assistant professor at the University of Utrecht prior to being with Microsoft and one of the most refreshing things in the presentation was to see a theoretical person using all his theory and knowledge of paradigms, semantics and whatnot to improve (I hope) production environments. All in all a great presentation, I&#8217;m still spaced-out about being able to access a lot of my functional programming things in C#.</p>
<p>Finally the fun anecdote Meijer gave during his presentation: Originally LINQ was called LIQ, but marketing changed it to LINQ as Language Integrated Query Object Relations would&#8217;ve become LIQOR otherwise. Can&#8217;t have that, nope.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2005/09/30/c-vb-and-linq/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On CRC Cards and Design</title>
		<link>http://hstuart.dk/2005/05/14/on-crc-cards-and-design/</link>
		<comments>http://hstuart.dk/2005/05/14/on-crc-cards-and-design/#comments</comments>
		<pubDate>Sat, 14 May 2005 15:09:32 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[book review]]></category>

		<guid isPermaLink="false">http://localhost/?p=172</guid>
		<description><![CDATA[Sometimes you just wish you had paid a bit more attention back then in the first few semesters of studying Computer Science, but oh no, you were too busy/young conquering the world. As such it has been that I have been overlooking The CRC Card Book for nearly five years now, where it has been [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you just wish you had paid a bit more attention back then in the first few semesters of studying Computer Science, but oh no, you were too busy/young conquering the world. As such it has been that I have been overlooking <a href="http://www.awprofessional.com/title/0201895358">The CRC Card Book</a> for nearly five years now, where it has been standing vigilantly on my bookcase. Since I have gotten more interested in teaching object-oriented methodologies over the past year and some, partially due to my internship, I figured it was on high time to take it down from its place on the shelf and read through it. I was not disappointed.</p>
<p>The book takes you through the object-oriented terms, strategies for evolving good designs, bringing the users into the process, and guiding everything along nicely by role-playing use cases, etc. While the ideas seem sound, psychologically speaking, I cannot help but feel that the described test cases work out just a bit too well. However, I am hoping to be pleasantly surprised and see that it can indeed work in a setting where people&#8217;s understanding of object-oriented design is rather rudimentary.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2005/05/14/on-crc-cards-and-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zooming the editor</title>
		<link>http://hstuart.dk/2005/03/07/zooming-the-editor/</link>
		<comments>http://hstuart.dk/2005/03/07/zooming-the-editor/#comments</comments>
		<pubDate>Mon, 07 Mar 2005 10:48:53 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://localhost/?p=178</guid>
		<description><![CDATA[A while back Sara Ford offered up &#8220;I love Visual Studio Core&#8221; t-shirts for people who wanted to contribute a bit of code for the Visual Studio 2005 PowerToys. Not passing up the chance for a t-shirt, I contributed code to a zoom control. Now the add-in is stored on gotdotnet, so good luck finding [...]]]></description>
			<content:encoded><![CDATA[<p>A while back <a href="http://blogs.msdn.com/saraford/">Sara Ford</a> offered up &#8220;I love Visual Studio Core&#8221; t-shirts for people who wanted to contribute a bit of code for the Visual Studio 2005 PowerToys. Not passing up the chance for a t-shirt, I contributed code to a <a href="http://blogs.msdn.com/saraford/archive/2005/02/14/372645.aspx">zoom control</a>. Now the add-in is stored on gotdotnet, so good luck finding a time when it isn&#8217;t crashed in some way.</p>
<p>For the interested parties, there&#8217;s a photo of the shirt on my floor, here&#8230;</p>
<div class="center">
  <img src="http://hstuart.dk/images/shirt.jpg" alt="Shirt"/>
</div>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2005/03/07/zooming-the-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Atomic Cellular Dysfunction</title>
		<link>http://hstuart.dk/2005/02/17/atomic-cellular-dysfunction/</link>
		<comments>http://hstuart.dk/2005/02/17/atomic-cellular-dysfunction/#comments</comments>
		<pubDate>Thu, 17 Feb 2005 19:10:30 +0000</pubDate>
		<dc:creator>Henrik Stuart</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://localhost/?p=181</guid>
		<description><![CDATA[It isn&#8217;t that my organism is self-destructing (much) that I&#8217;ve picked this rather funky topic for today&#8217;s post, nay, it is far more sinister and dark &#8211; it is the topic of a contest that I participated in, together with Noah Adler last month, a contest that was about creating a game in 48 hours [...]]]></description>
			<content:encoded><![CDATA[<p>It isn&#8217;t that my organism is self-destructing (much) that I&#8217;ve picked this rather funky topic for today&#8217;s post, nay, it is far more sinister and dark &#8211; it is the topic of a contest that I participated in, together with <a href="http://www.noahadler.com">Noah Adler</a> last month, a contest that was about creating a game in 48 hours to the theme: Atomic Cellular Dysfunction.</p>
<p>We managed to create, within the 48 hours, a lovely game in style with the games of the 80s that we have both grown up on and loved, so without further ado, we bring <a href="http://hstuart.dk/files/ACD.msi">Atomic Cellular Dysfunction</a> to the world. We hope you will enjoy it as much as we enjoyed PacMan and the other great games of our time.</p>
]]></content:encoded>
			<wfw:commentRss>http://hstuart.dk/2005/02/17/atomic-cellular-dysfunction/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

