<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://www.mechanicalrobotfish.com" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>mechanical robot fish - The mixed-up words of Michael Francis Booth</title>
 <link>http://www.mechanicalrobotfish.com/frontpage</link>
 <description>The basic front page view.</description>
 <language>en</language>
<item>
 <title>Checking out an open-source git project: the right way</title>
 <link>http://www.mechanicalrobotfish.com/posts/127-checking-out-open-source-git-project-right-way</link>
 <description>&lt;p&gt;(&lt;em&gt;Paraphrased from &lt;a href=&quot;http://blog.insoshi.com/2008/10/14/setting-up-your-git-repositories-for-open-source-projects-at-github/&quot;&gt;Long Nguyen&amp;#8217;s guide to checking out projects from GitHub&lt;/a&gt; &amp;#8212; which is excellent, except that Long uses the name &amp;#8220;long&amp;#8221; for too many different things, making the code hard for mere mortals to read.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Suppose you would like to work on the open-source Insoshi project. You have the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; of its official git&amp;nbsp;repository:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git://github.com/insoshi/insoshi.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You could simply clone this &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; to your own&amp;nbsp;machine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/insoshi/insoshi.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;after which you could mess around with your local copy as much as you like. But it&amp;#8217;s hard to share a local repository with your friends, or among several machines, so perhaps you&amp;#8217;d rather create a private fork on a server somewhere. It&amp;#8217;s easy to do this with a GitHub-hosted project like Insoshi &amp;#8212; you get a GitHub account, then press GitHub&amp;#8217;s &amp;#8220;fork&amp;#8221; button, and you rewarded with the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; for your own personal GitHub-hosted&amp;nbsp;fork:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git@github.com:mechfish/insoshi.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you could make a local clone of that remote&amp;nbsp;fork:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git@github.com:mechfish/insoshi.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;but there are disadvantages to that. One is that the local clone will have a different parent: its &lt;code&gt;origin&lt;/code&gt; will be remote fork, while the remote fork&amp;#8217;s &lt;code&gt;origin&lt;/code&gt; is the official project repository. Ideally, you would want the two repositories to be interchangeable, so that you won&amp;#8217;t get confused when comparing them, and so you can upload the local version to replace the remote version if it gets lost or&amp;nbsp;corrupted.&lt;/p&gt;

&lt;p&gt;You&amp;#8217;d also like to be able to pull changes from the official repository directly into your local copy, then push them up to the remote fork, rather than having to pull every change forward through the chain: official &amp;#x2192; remote fork &amp;#x2192; local copy. That&amp;#8217;s&amp;nbsp;painful.&lt;/p&gt;

&lt;p&gt;So here&amp;#8217;s what to&amp;nbsp;do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/insoshi/insoshi.git
$ cd insoshi
$ git branch devel master
$ git checkout devel
$ git remote add fork git@github.com:mechfish/insoshi.git
$ git fetch fork
$ git push fork devel:refs/heads/devel
$ git config branch.devel.remote fork
$ git config branch.devel.merge refs/heads/devel
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&amp;#8217;s what these commands&amp;nbsp;accomplish:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the official repository and &lt;code&gt;cd&lt;/code&gt; into the local&amp;nbsp;copy.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;devel&lt;/code&gt; branch to develop on. Note that if we want to base our development branch on the &amp;#8220;edge&amp;#8221; version of the project instead of the stable version we should do this instead:
&lt;code&gt;$ git branch --track edge origin/edge; git branch devel edge&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Checkout our new &lt;code&gt;devel&lt;/code&gt;&amp;nbsp;branch.&lt;/li&gt;
&lt;li&gt;Add a remote named &amp;#8220;fork&amp;#8221; that points to our private fork on the remote&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;Fetch the remote fork&amp;#8217;s&amp;nbsp;contents.&lt;/li&gt;
&lt;li&gt;Push our new &lt;code&gt;devel&lt;/code&gt; branch to the remote fork, where it should have the same&amp;nbsp;name.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;config&lt;/code&gt; for the &lt;code&gt;devel&lt;/code&gt; branch so that it automatically pushes changes to the &lt;code&gt;devel&lt;/code&gt; branch on the remote fork when we do a plain &lt;code&gt;git push&lt;/code&gt;, and automatically pulls from the &lt;code&gt;devel&lt;/code&gt; branch on the remote fork when we do a plain &lt;code&gt;git pull&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that with this setup you automatically get the feature that a &lt;code&gt;git push&lt;/code&gt; will push up all changes to all branches, including the &lt;code&gt;master&lt;/code&gt; branch. (That&amp;#8217;s because the default refspec for remotes is &lt;code&gt;refs/heads/*:refs/heads/*&lt;/code&gt;.) So you can pull changes from &lt;code&gt;origin&lt;/code&gt; directly to your local copy, with the assurance that those changes will be automatically migrated to your remote fork repository when you&amp;nbsp;push.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/127-checking-out-open-source-git-project-right-way#comments</comments>
 <pubDate>Fri, 07 Nov 2008 13:03:01 -0500</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">127 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Installing PHP, Apache, MySQL, and Ruby on Mac OS 10.5 Leopard</title>
 <link>http://www.mechanicalrobotfish.com/posts/126-installing-php-apache-mysql-and-ruby-mac-os-105-leopard</link>
 <description>&lt;p&gt;If you want to get up and running quickly using Drupal on Mac &lt;span class=&quot;caps&quot;&gt;OS&lt;/span&gt; 10.5 your best bet is to use &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt;, &lt;a href=&quot;http://www.sysarchitects.com/node/58&quot;&gt;as John VanDyk suggests in his comments&lt;/a&gt;. There are &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt; setup instructions &lt;a href=&quot;http://drupal.org/node/66187&quot;&gt;on Drupal.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But I decided to try moving away from &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt;. One reason is that &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt; doesn&amp;#8217;t come with certain features &amp;#8212; for example, I&amp;#8217;m told that it&amp;#8217;s hard to get &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; working. Another is that the upgrade cycle for &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; and MySQL is different from that of &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt;, and I sometimes want to be able to roll my own upgrade on my own timeframe. In addition, I want to play with Ruby technologies like &lt;a href=&quot;http://www.merbivore.com/&quot;&gt;Merb&lt;/a&gt; and &lt;a href=&quot;http://rack.rubyforge.org/&quot;&gt;Rack&lt;/a&gt; and &lt;a href=&quot;http://code.macournoyer.com/thin/&quot;&gt;Thin&lt;/a&gt;, and I didn&amp;#8217;t relish trying to hack them into &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt;&amp;#8217;s config files &amp;#8212; though it would probably be possible to do so, the Ruby docs and blogs tend to be aimed at people who are working outside of&amp;nbsp;&lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;So I&amp;#8217;ve just gotten everything installed. Here&amp;#8217;s a quick sketch of the&amp;nbsp;process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Follow &lt;a href=&quot;http://hivelogic.com/articles/2007/11/installing-mysql-on-mac-os-x&quot;&gt;Dan Benjamin&amp;#8217;s instructions for compiling MySQL&lt;/a&gt;. This will involve creating &lt;code&gt;/usr/local&lt;/code&gt; and adding it to your path, assuming you haven&amp;#8217;t already done&amp;nbsp;so.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m with &lt;a href=&quot;http://www.sysarchitects.com/node/58&quot;&gt;VanDyk&lt;/a&gt;, who suggests running &lt;code&gt;mysql_secure_installation&lt;/code&gt; once you have MySQL&amp;nbsp;installed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follow &lt;a href=&quot;http://hivelogic.com/articles/2008/02/ruby-rails-leopard&quot;&gt;Benjamin&amp;#8217;s instructions&lt;/a&gt; for compiling your own Ruby and Rubygems. This is a more dubious move, since Apple has provided preinstalled versions of Ruby and Gems in Leopard, and they work pretty well. But I decided to install my own version so that I can keep control over the&amp;nbsp;upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I recommend avoiding the stock Apache. I spent a while trying to compile a &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; that would work with it, and ran into trouble. Instead, install &lt;a href=&quot;http://www.macports.org/&quot;&gt;MacPorts&lt;/a&gt; and use that to &lt;a href=&quot;http://seancoates.com/php-5-2-5-on-leopard&quot;&gt;install Apache, then download and compile &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that I installed MacPorts&amp;#8217; Apache, then downloaded and built the &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; source myself, using the following &lt;code&gt;./configure&lt;/code&gt;&amp;nbsp;options:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; ./configure --prefix=/usr/local/php \
--with-apxs2=/opt/local/apache2/bin/apxs \
--with-mysql=/usr/local/mysql \
--with-curl --with-pgsql=shared \
--with-pdo-pgsql=shared,/usr/local/pgsql \
--with-pdo-mysql=shared,/usr/local/mysql \
--with-mcrypt=shared,/opt/local \
--with-openssl=shared,/opt/local \
--with-pear \
--with-gd \
--with-jpeg-dir=/opt/local \
--with-png-dir=/opt/local \
--without-iconv
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#8217;m not sure there&amp;#8217;s a good reason to do this instead of just using MacPorts&amp;#8217; &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt;. For that matter, I&amp;#8217;m not sure that using your own MySQL is better than having MacPorts install MySQL, or using the binary distribution from MySQL &lt;span class=&quot;caps&quot;&gt;AG&lt;/span&gt;. There are lots of options. But these options seemed to work for&amp;nbsp;me.&lt;/p&gt;

&lt;p&gt;Of course, you&amp;#8217;ve also got to set up a &lt;code&gt;php.ini&lt;/code&gt; and an &lt;code&gt;httpd.conf&lt;/code&gt; and get PHP and Apache pointing at them. And I&amp;#8217;ve still got &lt;a href=&quot;http://2bits.com/articles/benchmarking-apc-vs-eaccelerator-using-drupal.html&quot;&gt;eAccelerator&lt;/a&gt; and &lt;a href=&quot;http://debuggable.com/posts/setting-up-xdebug-on-mac-os-x-or-win32-linux:480f4dd6-0240-4a90-8fa1-4e41cbdd56cb&quot;&gt;XDebug&lt;/a&gt; to install. It&amp;#8217;s a bit of work. I&amp;#8217;d advise anybody who wants to avoid trouble to stick with the &lt;span class=&quot;caps&quot;&gt;MAMP&lt;/span&gt;&amp;nbsp;option.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/126-installing-php-apache-mysql-and-ruby-mac-os-105-leopard#comments</comments>
 <pubDate>Tue, 04 Nov 2008 15:24:01 -0500</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">126 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Actuarial</title>
 <link>http://www.mechanicalrobotfish.com/posts/125-actuarial</link>
 <description>&lt;p&gt;As usual, &lt;a href=&quot;http://xkcd.com/493/&quot;&gt;today&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;XKCD&lt;/span&gt;&lt;/a&gt; makes you&amp;nbsp;think.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Life-Line&quot;&gt;Life-Line&lt;/a&gt;, the story of an inventor who learns how to predict the time of a person&amp;#8217;s death to within a single hour, was the first story that Robert Heinlein ever sold, in 1939. As in all Heinlein stories, the great part of this story is the portrait of a character: The inventor, who successfully (and a bit annoyingly) remains calm and rational about the fact of death, including his own death, even as everyone around him is freaking&amp;nbsp;out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Asimov treated the story of the soothsayer as a grand historical epic (&lt;em&gt;Foundation&lt;/em&gt;); Clarke wrote stories full of spiritual awe (e.g. &lt;em&gt;The Nine Billion Names of God&lt;/em&gt;, &lt;em&gt;2001&lt;/em&gt;), but Heinlein boiled it all down to this one guy in a shabby office. He was the Raymond Chandler of science fiction &amp;#8212; until the 1960s, at any&amp;nbsp;rate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kevin Kelly has a &lt;a href=&quot;http://kk.org/ct2/2007/09/my-life-countdown-1.php&quot;&gt;countdown clock of the days he has left to live&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;My friend Stewart Brand, who is now 69, has been arranging his life in blocks of 5 years. Five years is what he says any project worth doing will take. From moment of inception to the last good-riddance, a book, a campaign, a new job, a start-up will take 5 years to play through. So, he asks himself, how many 5 years do I have left? He can count them on one hand even if he is lucky. So this clarifies his choices. If he has less than 5 big things he can do, what will they&amp;nbsp;be?&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I appear to have &lt;a href=&quot;http://www.cdc.gov/nchs/fastats/lifexpec.htm&quot;&gt;eight big things I can do&lt;/a&gt; &amp;#8212; forty years, 14691&amp;nbsp;days.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I think that a timeline which plotted the lifetimes of famous people &amp;#8212; including the expected lifetimes of people who are alive right now &amp;#8212; would be a great tool. I&amp;#8217;ve loved timelines ever since I thumbed through &lt;a href=&quot;http://www.amazon.com/Timetables-History-Horizontal-Linkage-People/dp/067174271X&quot;&gt;The Timetables of History&lt;/a&gt; as a&amp;nbsp;kid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need to occasionally think on a timescale that is longer than a single human life. You need to accept that people&amp;#8217;s lives have arcs, like stories. You need to remember that &lt;a href=&quot;http://www.longnow.org/&quot;&gt;the world will go on after you&lt;/a&gt;.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/125-actuarial#comments</comments>
 <pubDate>Fri, 24 Oct 2008 10:39:23 -0400</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">125 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Drupal&#039;s Data Structures and the Properties Pattern</title>
 <link>http://www.mechanicalrobotfish.com/posts/124-drupals-data-structures-and-properties-pattern</link>
 <description>&lt;p&gt;I might be crazy, but as I read &lt;a href=&quot;http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html#Intro&quot;&gt;Steve Yegge&amp;#8217;s essay on the Properties Pattern&lt;/a&gt; I felt as if I was being introduced to something I already knew. And that&amp;#8217;s not just because the essay describes Javascript. I think that&amp;#8217;s because Properties lists are the fundamental Drupal data&amp;nbsp;structure.&lt;/p&gt;

&lt;p&gt;This line stuck&amp;nbsp;out:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I&amp;#8217;ve talked about the main problems imposed by the Properties pattern: performance, data integrity, and navigability/queryability. They&amp;#8217;re all trade-offs; you&amp;#8217;re sacrificing in these areas in order to achieve big wins in flexibility and open-ended future extensibility for users you may never&amp;nbsp;meet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yep, that sure sounds like Drupal&amp;#8217;s &lt;code&gt;$node&lt;/code&gt;, &lt;code&gt;$user&lt;/code&gt;, and &lt;code&gt;$form&lt;/code&gt; objects to&amp;nbsp;me.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/124-drupals-data-structures-and-properties-pattern#comments</comments>
 <pubDate>Wed, 22 Oct 2008 17:59:34 -0400</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">124 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>A Horse Designed By an Open-Source Committee</title>
 <link>http://www.mechanicalrobotfish.com/posts/123-a-horse-designed-by-open-source-committee</link>
 <description>&lt;p&gt;I have only three things to say about the heroic efforts of &lt;a href=&quot;http://www.markboultondesign.com/news/detail/initial_wordmark_designs/&quot;&gt;Mark Boulton&lt;/a&gt; to come up with a design for a Drupal wordmark that will satisfy the entire Drupal&amp;nbsp;community.&lt;/p&gt;

&lt;p&gt;First: Mark is a brave&amp;nbsp;man.&lt;/p&gt;

&lt;p&gt;Second: I hereby officially delegate my opinion on the Drupal wordmark to Mark, Dries Buytaert, Barry Jaspan, and Angie Byron. If they like it, I like it, by definition. My desire to further influence the decision is more than trumped by my belief that such artistic decisions can&amp;#8217;t be made by a giant, public&amp;nbsp;committee.&lt;/p&gt;

&lt;p&gt;Finally: Voting. Draw up three strong contenders, then let the community respond to a questionnaire. Don&amp;#8217;t request &lt;em&gt;too&lt;/em&gt; much free-form feedback in open forums during your design process. You will go stark raving&amp;nbsp;mad. &lt;/p&gt;

&lt;p&gt;The firm that recently redesigned my &lt;a href=&quot;http://cwru.edu/&quot;&gt;alma mater&amp;#8217;s logo&lt;/a&gt; did a great job with this: The first I heard of the project was when I received an email link to an online questionnaire. The questionnaire took ten or twenty minutes to complete, featured three variations of the logo, and asked all sorts of fuzzy questions &amp;#8212; I can&amp;#8217;t remember any of them, but they were something like &amp;#8220;does this logo express the intellectual qualities you associate with the university.&amp;#8221; Or whatever. In retrospect, it didn&amp;#8217;t really matter what the questions were &amp;#8212; the important thing was that they asked a sufficient number of important-sounding questions to convince me that I was participating in a &lt;em&gt;thorough&lt;/em&gt;, &lt;em&gt;serious&lt;/em&gt; decision-making&amp;nbsp;process.&lt;/p&gt;

&lt;p&gt;Then, a few months later, the university announced the winner, and, lo! I was happy. Because, hey, the new logo looks pretty good! And because I had been&amp;nbsp;asked.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/123-a-horse-designed-by-open-source-committee#comments</comments>
 <pubDate>Tue, 16 Sep 2008 20:18:02 -0400</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">123 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Javascript: Packing, Unpacking, and Beautifying</title>
 <link>http://www.mechanicalrobotfish.com/posts/122-javascript-packing-unpacking-and-beautifying</link>
 <description>&lt;p&gt;A lot of the Javascript on the web ships in compressed form. This is particularly irritating if you discover that, say, Drupal 5&amp;#8217;s &lt;a href=&quot;http://drupal.org/project/jstools&quot; title=&quot; Javascript Tools&quot;&gt;jstools&lt;/a&gt; module has bugs that you&amp;#8217;d like to fix, but the module ships with nothing but compressed versions of the Javascript code. (&lt;em&gt;What were they thinking?&lt;/em&gt;) &lt;/p&gt;

&lt;p&gt;A common method of packing Javascript is &lt;a href=&quot;http://dean.edwards.name/packer/&quot; title=&quot;the packer tool&quot;&gt;Dean Edwards&amp;#8217; packer algorithm&lt;/a&gt;, which has a convenient online version. You can recognize code that&amp;#8217;s been through the packer by looking for the cute function signature at the&amp;nbsp;beginning:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;eval(function(p,a,c,k,e,r){...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It turns out that you can unpack code like this using Dean Edwards&amp;#8217; &lt;a href=&quot;http://dean.edwards.name/packer/&quot;&gt;online tool&lt;/a&gt;. This isn&amp;#8217;t immediately apparent, because the tool doesn&amp;#8217;t enable this feature by default (presumably because it&amp;#8217;s trying to pretend that packing is an effective form of code obfuscation). But if you run &lt;a href=&quot;http://yaisb.blogspot.com/2006/10/defeating-dean-edwards-javascript.html&quot;&gt;the handy &amp;#8220;reEnable&amp;#8221; bookmarklet&lt;/a&gt; the packer page becomes an &amp;#8220;unpacker&amp;#8221;&amp;nbsp;page.&lt;/p&gt;

&lt;p&gt;Once your function is unpacked you are only halfway home, because it will look like this example (from the &lt;a href=&quot;http://stilbuero.de/jquery/history/index.html&quot;&gt;jQuery History/Remote plugin&lt;/a&gt; included with Drupal&amp;nbsp;jstools):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(function($){$.ajaxHistory=new function(){var c=&#039;historyReset&#039;;var k=location.hash;var e=null;var g;this.update=function(){};var h=function(){$(&#039;.remote-output&#039;).empty()};$(document).bind(c,h);if($.browser.msie){var f,initialized=false;$(function(){f=$(&#039;&amp;lt;iframe style=&quot;display: none;&quot;&amp;gt;&amp;lt;/iframe&amp;gt;&#039;).appendTo(document.body).get(0);var ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No line breaks, not so readable. So feed it through the &lt;a href=&quot;http://elfz.laacz.lv/beautify/&quot;&gt;online beautifier for Javascript&lt;/a&gt; and you&amp;#8217;ll&amp;nbsp;get&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(function($) {
$.ajaxHistory = new
function() {
    var c = &#039;historyReset&#039;;
    var k = location.hash;
    var e = null;
    var g;
    this.update = function() {};
    var h = function() {
        $(&#039;.remote-output&#039;).empty()
    };
    $(document).bind(c, h);
    if ($.browser.msie) {
        var f, initialized = false;
        $(function() {
           ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Much&amp;nbsp;better.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/122-javascript-packing-unpacking-and-beautifying#comments</comments>
 <pubDate>Wed, 18 Jun 2008 16:00:04 -0400</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">122 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>The spammers have me outnumbered</title>
 <link>http://www.mechanicalrobotfish.com/posts/121-the-spammers-have-me-outnumbered</link>
 <description>&lt;p&gt;Whew, just cleaned out several hundred spam comments. Those bots are &lt;em&gt;prolific&lt;/em&gt;. I guess it&amp;#8217;s time to see what Dries Buytaert&amp;#8217;s &lt;a href=&quot;http://mollom.com/&quot;&gt;anti-spam project&lt;/a&gt; is all&amp;nbsp;about&amp;#8230;&lt;/p&gt;

&lt;p&gt;In the meantime, lest you suspect that I&amp;#8217;ve made a New Year&amp;#8217;s resolution to stop writing, I should tell you that I&amp;#8217;ve been spending too much of my writing time posting as &lt;a href=&quot;http://news.ycombinator.com/user?id=mechanical_fish&quot;&gt;mechanical_fish&lt;/a&gt; on &lt;a href=&quot;http://news.ycombinator.com&quot;&gt;Hacker News&lt;/a&gt;, a fairly awesome site full of people who know much more about software than&amp;nbsp;I.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;: From my &lt;a href=&quot;http://www.mollom.com&quot;&gt;Mollom&lt;/a&gt; page: &amp;#8220;Mollom blocked 7360 spam attempts the past 10 days&amp;#8221;. So far, so good. Mollom is hereby&amp;nbsp;recommended.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt; 2: That seems to have been a typo on the Mollom site: I think they meant &lt;em&gt;736&lt;/em&gt; spam attempts over 10 days. Much more believeable. And still&amp;nbsp;scary.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/121-the-spammers-have-me-outnumbered#comments</comments>
 <pubDate>Sun, 11 May 2008 02:11:07 -0400</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">121 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Drupal and PHPass, Macs and GPG</title>
 <link>http://www.mechanicalrobotfish.com/posts/120-drupal-and-phpass-macs-and-gpg</link>
 <description>&lt;p&gt;As I was setting up a new Drupal site, I decided to try out the hilariously named &lt;a href=&quot;http://drupal.org/project/phpass&quot;&gt;phpass&lt;/a&gt; module. (I cannot read that as &amp;#8220;&lt;span class=&quot;caps&quot;&gt;PH&lt;/span&gt; Pass&amp;#8221; to save my life. It always comes out as&amp;#8230; something&amp;nbsp;else.)&lt;/p&gt;

&lt;p&gt;The good news about this module is that it builds upon a &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; project called, um, &lt;a href=&quot;http://www.openwall.com/phpass/&quot;&gt;phpass&lt;/a&gt; to add better password hashing to Drupal. The traditional way to handle passwords is to ask the user for one, compute a hash function on it, and store the hashed version. Unix systems use the Unix &lt;code&gt;crypt&lt;/code&gt; utility to make the hash. Some newer and more naive systems, like core Drupal, use &lt;code&gt;MD5&lt;/code&gt; hashing, presumably because it&amp;#8217;s newer (and, therefore, niftier by definition) and also because it&amp;#8217;s&amp;nbsp;faster.&lt;/p&gt;

&lt;p&gt;Unfortunately, it&amp;#8217;s &lt;a href=&quot;http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/&quot;&gt;a bad idea to use a fast hash function to hash your passwords&lt;/a&gt;, because the speed makes the brute-force attacks that much more efficient. The Right Thing to do, if we trust the professionals at &lt;a href=&quot;http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/&quot;&gt;Matasano Chargen&lt;/a&gt;, is to use an adaptive hashing scheme like &lt;code&gt;bcrypt&lt;/code&gt;, which is tricky and slow, and can be made slower and trickier as computers get faster and&amp;nbsp;faster.&lt;/p&gt;

&lt;p&gt;Unfortuately, neither my Mac nor my Ubuntu deployment box supports &lt;code&gt;CRYPT_BLOWFISH&lt;/code&gt;, the encryption scheme that&amp;#8217;s needed for all-out bcrypt support. So I am using the phpass fallback scheme for now. I could try to install &lt;code&gt;CRYPT_BLOWFISH&lt;/code&gt; using the &lt;a href=&quot;http://www.hardened-php.net/&quot;&gt;Suhosin &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; hardening extension&lt;/a&gt;, but would need to test this carefully to make sure I don&amp;#8217;t break Drupal in the&amp;nbsp;process.&lt;/p&gt;

&lt;p&gt;In the meantime, I got halfway into the Suhosin downloading process before I decided to put it off until tomorrow. Part I of the process was to finally install &lt;a href=&quot;http://www.gnupg.org/&quot;&gt;Gnu Privacy Guard&lt;/a&gt;, which I have always resisted because it seemed to be a usability horrorshow with few actual uses. I only know two people who really seem to use &lt;span class=&quot;caps&quot;&gt;GPG&lt;/span&gt;-signed mail, let alone &lt;span class=&quot;caps&quot;&gt;GPG&lt;/span&gt;-encrypted mail. But it turns out that there&amp;#8217;s now a &lt;a href=&quot;http://www.wasuvi.com/?page_id=2368&quot;&gt;handy set of instructions for installing &lt;span class=&quot;caps&quot;&gt;GPG&lt;/span&gt; on a Mac&lt;/a&gt; using the &lt;a href=&quot;http://macgpg.sourceforge.net/&quot;&gt;MacGPG project&lt;/a&gt;. And I might even get &lt;span class=&quot;caps&quot;&gt;GPG&lt;/span&gt; working with Mail once &lt;a href=&quot;http://www.sente.ch/software/GPGMail/English.lproj/GPGMail.html&quot;&gt;the GPGMail utility&lt;/a&gt; finishes being ported to Mac &lt;span class=&quot;caps&quot;&gt;OS&lt;/span&gt;&amp;nbsp;10.5.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/120-drupal-and-phpass-macs-and-gpg#comments</comments>
 <pubDate>Sun, 30 Dec 2007 14:28:26 -0500</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">120 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Installing a git server using gitosis</title>
 <link>http://www.mechanicalrobotfish.com/posts/119-installing-git-server-using-gitosis</link>
 <description>&lt;p&gt;I&amp;#8217;m switching all my personal projects to &lt;a href=&quot;http://git.or.cz/&quot;&gt;git&lt;/a&gt; from &lt;a href=&quot;http://svnbook.red-bean.com/&quot;&gt;Subversion&lt;/a&gt;. After watching the &lt;a href=&quot;http://peepcode.com/products/git&quot;&gt;Peepcode git screencast&lt;/a&gt;, Subversion feels oh-so-2002 and I can&amp;#8217;t wait to bury it&amp;nbsp;forever.&lt;/p&gt;

&lt;p&gt;First we have to get git running on my Ubuntu server. I&amp;nbsp;tried&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install git-core #do not do this!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;but that led to trouble down the line. Better to just fetch the source and build from&amp;nbsp;that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install libexpat1-dev zlibc curl gettext
cd ~/src
wget http://www.kernel.org/pub/software/scm/git/git-1.5.4.rc2.tar.gz
cd git-1.5.4.rc2
make prefix=/usr/local all
sudo make prefix=/usr/local install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, following &lt;a href=&quot;http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way&quot;&gt;the excellent instructions on scie.nti.st&lt;/a&gt;, we grab the gitosis&amp;nbsp;code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd ~/src
git clone git://eagain.net/gitosis.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd gitosis
sudo apt-get install python-setuptools
python setup.py install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we have to create a git user to own the&amp;nbsp;repositories:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo adduser \
    --system \
    --shell /bin/sh \
    --gecos &#039;git version control&#039; \
    --group \
    --disabled-password \
    --home /home/git \
    git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We copy my public ssh key into &lt;code&gt;/tmp/id_rsa.pub&lt;/code&gt;, then&amp;nbsp;run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo -H -u git gitosis-init &amp;lt; /tmp/id_rsa.pub
sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s the end of the server-side setup! On the local machine, we check out the files that are needed to control the server. First we have to account for the fact that I run &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; on a nonstandard port: edit &lt;code&gt;~/.ssh/config&lt;/code&gt; and put this&amp;nbsp;inside:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Host www.example.com
    Port 32767
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then you can&amp;nbsp;do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git@YOUR_SERVER_HOSTNAME:gitosis-admin.git
cd gitosis-admin
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the directory where you administer&amp;nbsp;gitosis.&lt;/p&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/119-installing-git-server-using-gitosis#comments</comments>
 <pubDate>Thu, 27 Dec 2007 22:47:53 -0500</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">119 at http://www.mechanicalrobotfish.com</guid>
</item>
<item>
 <title>Social Networks: Stop Designing Out The Fun</title>
 <link>http://www.mechanicalrobotfish.com/posts/118-social-networks-stop-designing-out-fun</link>
 <description>&lt;p&gt;Today in the news we find that Google is &lt;a href=&quot;http://slashdot.org/~Felipe+Hoffa/journal/191246&quot;&gt;adding lame, privacy-defeating &amp;#8220;social networking&amp;#8221; features to popular apps without user consent&lt;/a&gt;. This comes on the heels of &lt;a href=&quot;http://www.zephoria.org/thoughts/archives/2007/12/11/facebooks_optou.html&quot;&gt;Facebook&amp;#8217;s Beacon trainwreck&lt;/a&gt;, which was preceded by a &lt;a href=&quot;http://www.danah.org/papers/FacebookAndPrivacy.html&quot;&gt;similar Facebook privacy trainwreck&lt;/a&gt;.
There are many lessons to learn from these incidents: That users really &lt;em&gt;do&lt;/em&gt; care about privacy as soon as you start abusing their data; that web users &lt;a href=&quot;http://icanhascheezburger.com/2007/09/09/do-not-want-7/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;DO&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;WANT&lt;/span&gt;&lt;/a&gt; to have the same persistent, verifiable &amp;#8212; and easily traced &amp;#8212; &lt;span class=&quot;caps&quot;&gt;ID&lt;/span&gt; attached to all their online actions; that my innate distrust of Gmail is not as paranoid as I once thought.
But let&amp;#8217;s focus on a fundamental problem: Social networking is one of the most significant developments on the web today, and our leading app designers apparently have &lt;em&gt;no clue&lt;/em&gt; about how socializing works and why we humans work so hard at&amp;nbsp;it.&lt;/p&gt;

&lt;h2&gt;Stop Designing the Neutron&amp;nbsp;Bomb&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;It would be trivial to design a better interface than &lt;span class=&quot;caps&quot;&gt;DOOM&lt;/span&gt; if the goal was to kill the bad guys as quickly as possible: give me a 2D map of the area with icons for enemy troops and let me drop bombs on them by clicking the icons. Presto: game over in a few seconds and the good guys win every time. That&amp;#8217;s the design you want if you are the Pentagon, but it makes for a boring game.
  &lt;span class=&quot;sig&quot;&gt;&lt;a&gt;Jakob&amp;nbsp;Nielsen&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Facebook and Google &amp;#8212; and, one fears, a bunch of current and future startups &amp;#8212; operate on the assumption that sharing links with your friends is a tedious chore. Telling your friends about your most recent purchases is a chore. Figuring out which addresses in your book correspond to your best friends is a chore. So they try to automate these chores away: In the spirit of Jakob Nielsen&amp;#8217;s high-efficiency first-person shooter, they build one big flat list of all your friends and offer you an elegant one-button interface:&amp;nbsp;&lt;span class=&quot;caps&quot;&gt;SOCIALIZE&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;Hello? &lt;strong&gt;People use social networks because they are fun.&lt;/strong&gt; Tweaking your Friend list is fun. Personally choosing the links to be sent to your friends is fun. Choosing when and how to poke people is fun. Flirting is fun! Deciding which of your friends should be introduced to each other is a source of social anxiety, but it is also&amp;nbsp;fun.&lt;/p&gt;

&lt;p&gt;Feel free to automate the cleaning of my laundry and the removal of my trash. I don&amp;#8217;t really enjoy those things. But &lt;strong&gt;stop thinking of my social life and my public persona as tasks that I want to outsource, instead of as hobbies that define my&amp;nbsp;personality.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Fun is Deadly&amp;nbsp;Serious&lt;/h2&gt;

&lt;p&gt;Perhaps I should stop writing right now. Once you&amp;#8217;ve told people to stop designing out the fun, is there any more to&amp;nbsp;say?&lt;/p&gt;

&lt;p&gt;Maybe. &lt;strong&gt;The problem with fun is that many people don&amp;#8217;t respect it.&lt;/strong&gt; They think it&amp;#8217;s frivolous, and trivial, and arbitrary. Because people share links &amp;#8220;just for fun&amp;#8221;, designers feel free to quietly, unilaterally change the way that shared links work. &amp;#8220;Why are you taking Google Reader so seriously?&amp;#8221;, they say. &amp;#8220;Lighten up and share your&amp;nbsp;data!&amp;#8221;&lt;/p&gt;

&lt;p&gt;These designers are insane. Fun is serious business. Just look at how animals have fun: Cats think that stalking fast-moving objects is fun, dogs think that herding and chasing are fun, gerbils think that burrowing and chewing are fun, and parrots think that &amp;#8212; believe it or not &amp;#8212; social networking is fun. For animals, &lt;strong&gt;fun is associated with the practice of vital survival&amp;nbsp;skills.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Humans work the same way. Reproduction? Fun. Looking at babies, especially your own? Fun. Hunting, watching birds, playing Half-Life? It&amp;#8217;s fun, and it&amp;#8217;s also a way to practice the stalking skills that you&amp;#8217;d use for hunting game or fighting wars. Chess? Strategic training for warfare. (Just ask any well-educated kid from the Middle Ages.) Gardening? Practice for farming. Stamp collecting and Pokemon? You&amp;#8217;re practicing taxonomy, exercising the parts of  your brain that evolved to remember which things you can eat, which things can eat &lt;em&gt;you&lt;/em&gt;, which are poisonous, which are likely to be found under trees in&amp;nbsp;July.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Social networking is one of the most fun things of all, because it&amp;#8217;s a survival skill that humans are heavily invested in.&lt;/strong&gt; We&amp;#8217;re &lt;em&gt;designed&lt;/em&gt; for it. Human language itself is a social networking&amp;nbsp;tool.&lt;/p&gt;

&lt;p&gt;Some fun activities are no longer vital for survival: We&amp;#8217;ve invested lots of time, energy, and money to ensure that I can eat without knowing how to tell one plant from another, defend myself without knowing how to shoot, and stay warm without flint and tinder. Social networking is not in this category. &lt;strong&gt;Social networking may be more important now than ever before in human history.&lt;/strong&gt; Many historical humans had very little interaction with strangers. They didn&amp;#8217;t marry anyone that their parents didn&amp;#8217;t already know, and their friends lived within a ten-minute walk. (Of course, even &lt;em&gt;these&lt;/em&gt; people had a social network that was too complicated for a computer to&amp;nbsp;manage.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern social networks are very complicated.&lt;/strong&gt; We travel a lot. We move through many different social groups during our lives. We have multiple overlapping circles of friends. We have technical friends, gaming friends, friends from work, friends from school, friendly customers, friendly teachers, friends we aspire to marry, friends with benefits, platonic friends. We have friends who we met once at a conference in 2006, friends who we went to college with but don&amp;#8217;t see more than once every three years, and friends who we used to see every day but who just moved to Idaho. We have relatives, who may or may not be our friends. We have the relatives of friends, and the friends of relatives. We have fundamentalist Christian friends and polyamorous anarchist&amp;nbsp;friends. &lt;/p&gt;

&lt;p&gt;Incidentally, we also have&amp;nbsp;enemies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mismanaging your social interactions can have terrible consequences.&lt;/strong&gt; It can cost you your reputation, your spouse, your children, your inheritance, your job, your career, your freedom, and your sanity. If you make the wrong friend, and that friend turns into a stalker, it can cost you your&amp;nbsp;life.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personally micromanaging your social network is&amp;nbsp;fun.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The reason it&amp;#8217;s fun is that humans are designed for it.&lt;/strong&gt; This, in turn, is because &lt;strong&gt;it&amp;#8217;s a vitally important personal skill that determines your income and your happiness.&lt;/strong&gt; This is especially true in the 21st&amp;nbsp;century.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nobody is going to entrust their social network to a computer, not ever.&lt;/strong&gt; Computers have not spent millions of years evolving their social skills. Computers are stupid. You have not solved the strong &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; problem. If, by chance, you &lt;em&gt;do&lt;/em&gt; invent a computer that is smarter than a human, nobody will trust that,&amp;nbsp;either.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build tools that empower people to make better decisions, not tools that try to make decisions for&amp;nbsp;them.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
 <comments>http://www.mechanicalrobotfish.com/posts/118-social-networks-stop-designing-out-fun#comments</comments>
 <pubDate>Wed, 26 Dec 2007 12:38:44 -0500</pubDate>
 <dc:creator>Mike</dc:creator>
 <guid isPermaLink="false">118 at http://www.mechanicalrobotfish.com</guid>
</item>
</channel>
</rss>
