<?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>Gingerlime &#187; Technology</title>
	<atom:link href="http://blog.gingerlime.com/category/technology/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.gingerlime.com</link>
	<description></description>
	<lastBuildDate>Tue, 07 Sep 2010 19:13:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>2nd edition of 1</title>
		<link>http://blog.gingerlime.com/2nd-edition-of-1</link>
		<comments>http://blog.gingerlime.com/2nd-edition-of-1#comments</comments>
		<pubDate>Mon, 06 Sep 2010 23:59:18 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[art]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=205</guid>
		<description><![CDATA[I was really pleased when my good friend chris asked me to help him with his edition of 1 project. I guess it was exciting working on an arts project. I also liked his project because randomness is an interesting concept, particularly when it comes to computers. Put very simply: computers have trouble picking stuff [...]]]></description>
			<content:encoded><![CDATA[<p>I was really pleased when my good friend <a href="http://christopherrawcliffe.com">chris</a> asked me to help him with his <a href="http://www.editionof1.org/Editionof1.org/edition_of_1_ABOUT.html">edition of 1</a> project. I guess it was exciting working on an arts project. I also liked his project because randomness is an interesting concept, particularly when it comes to computers. Put very simply: computers have trouble picking stuff at random.<br />
<span id="more-205"></span><br />
Chris&#8217;s project was to pick a random image from the internet and present it on screen. It sounds fairly simple, and even slightly boring at first, but it creates a rather magical effect (and slightly addictive after a short while). The combination and sequence of images is interesting. The randomness of selection applies to many layers. How do you pick a random number using a deterministic process (like a computer)? How can you select an image at random if the search engine indexed it based on predefined criteria? What about the selection of the search engine you use? Or any other part of the process. I suppose those questions are only a part of what made this project interesting (for me anyway). </p>
<p>Chris initially used the <a href="http://www.ghettodriveby.com/">ghettodriveby</a> website, which does just that &#8211; picks a random image. So in that respsect, there wasn&#8217;t a great deal of technology or artistic innovation. Chris did however use two monitors and stretched the images on screen, to create a really cool effect &#8211; contrasting two random images. Also when displayed full screen, without any context or text, the impact is quite different, and even more so in a gallery space (I have to admit I have never seen edition of 1 in a gallery, not yet anyway).</p>
<p><a href="http://blog.gingerlime.com/wp-content/uploads/2010/09/sausage.jpg"><img src="http://blog.gingerlime.com/wp-content/uploads/2010/09/sausage-225x300.jpg" alt="" title="editionof1" width="225" height="300" style="border: 0pt none; float:right; padding-left:20px; padding-bottom:50px"/></a></p>
<p><br/><br />
For the impatient &#8211; here&#8217;s the <a href="http://www.gingerlime.com/editionof1.html">temporary end result</a>. Wait for the image to change.<br />
<br/><br />
So my first task was to mimic or copy ghettodriveby. The second one was to create a 2nd version for the <a href="http://www.deptfordx.webeden.co.uk/">Deptford X</a> festival. On the 2nd version, images will be searched at random from a limited set of key words &#8211; having to do with Deptford. </p>
<p>Why not re-use ghettodriveby? There were a couple of reasons to re-invent the wheel here:</p>
<ol>
<li>ghettodriveby isn&#8217;t very clear about the rights to use it, especially the way chris modified it</li>
<li>Chris had no control over ghettodriveby. If it goes down or changes, edition of 1 won&#8217;t work</li>
<li>When using a custom keyword search, ghettodriveby seemed to always return the same image &#8211; this was a real problem for Deptford X</li>
<li>because it&#8217;s fun to DIY</li>
</ol>
<p>So the first task (which ended up being put aside for the deptford edition) was reasonably easy. Google provides a <a href="http://code.google.com/apis/ajaxsearch/documentation/#API_Overview">search API</a> which allows you to search for images. Whilst there&#8217;s no option to search for a <em>random</em> image, we could easily use a random word to search for. Picking up a random word was the next challenge. I then figured out the best way to get a long list of words is <a href="http://www.wiktionary.org/">wiktionary</a>. You can download their whole database in xml format, and then extract the terms. I created a little python proof-of-concept and it seems to work well. I didn&#8217;t include the random word selection into it, but that&#8217;s quite easy.</p>
<div class="codesnip-container" >
<div class="python codesnip"><span class="co1"># img_search.py</span></p>
<p><span class="kw1">import</span> <span class="kw3">urllib2</span><br />
<span class="kw1">import</span> cjson<br />
<span class="kw1">import</span> <span class="kw3">sys</span></p>
<p><span class="co1"># usage: img_search.py [search term]</span><br />
url = <span class="br0">&#40;</span><span class="st0">&#8216;http://ajax.googleapis.com/ajax/services/search/images?v=1.0&amp;q=%s&amp;start=1&#8242;</span> <span class="sy0">%</span> <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span> </p>
<p>request = <span class="kw3">urllib2</span>.<span class="me1">Request</span><span class="br0">&#40;</span>url, <span class="kw2">None</span>, <span class="br0">&#123;</span><span class="st0">&#8216;Referer&#8217;</span>: <span class="st0">&#8216;http://www.your-domain.com&#8217;</span><span class="br0">&#125;</span><span class="br0">&#41;</span><br />
response = <span class="kw3">urllib2</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span>request<span class="br0">&#41;</span><br />
results = cjson.<span class="me1">decode</span><span class="br0">&#40;</span>response.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">for</span> i <span class="kw1">in</span> results<span class="br0">&#91;</span><span class="st0">&#8216;responseData&#8217;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;results&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> i<span class="br0">&#91;</span><span class="st0">&#8216;url&#8217;</span><span class="br0">&#93;</span></div>
</div>
<p><a href="http://blog.gingerlime.com/wp-content/uploads/2010/09/clock.jpg"><img src="http://blog.gingerlime.com/wp-content/uploads/2010/09/clock-300x227.jpg" alt="" title="clock" width="300" height="227" style="border: 0pt none; float:left; padding-right:20px; padding-bottom:50px" /></a></p>
<p>The problem I faced when narrowing down the search into only a few words (like &#8216;deptford&#8217;) was that the google api seems to limit the maximum results to 60. I have no idea why, but if the <em>start</em> parameter was set to anything higher than 60, google api choked. No results. Bummer. The show was meant to run for 10 days, changing the image every 10 seconds. 60 images per search term isn&#8217;t going to cut it.</p>
<p>One workaround was to mix the term with another word, perhaps at random. maybe do a combination of &#8216;deptford&#8217; and &#8216;book&#8217;, &#8216;cat&#8217;, &#8216;morning&#8217; or &#8216;baguette&#8217; (especially &#8216;baguette&#8217;). It wasn&#8217;t elegant though, and not random enough.</p>
<p>So we then searched for alternatives. <a href="http://developer.yahoo.com/search/boss/">Yahoo BOSS</a> turned out to provide a very similar api, and after going through the motions of getting the API key (which yahoo requires), it looked like yahoo didn&#8217;t limit the results. Well, it kinda did, but much higher than 60. I did some experiments and somewhere above 1,000, yahoo seems to always return the same image. 1,000 is manageable though.</p>
<p>Despite having very little experience with php, and not liking it as much as I like python, it seemed like a better choice. You can run php on almost any server. So I then had to work out how to turn my python code into php. This is the end result (more or less). This php only returns a random URL based on a set of keywords, each with its own maximum count (some search expressions might not even return 1,000 results).</p>
<div class="codesnip-container" >
<div class="php codesnip"><span class="kw2">&lt;?php</span></p>
<p><span class="kw2">function</span> getLink<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$search_arr</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
<span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;term&quot;</span><span class="sy0">=&gt;</span><span class="st0">&quot;deptford&quot;</span><span class="sy0">,</span> <span class="st0">&quot;max&quot;</span><span class="sy0">=&gt;</span><span class="nu0">1000</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
<span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;term&quot;</span><span class="sy0">=&gt;</span><span class="st0">&quot;lewisham&quot;</span><span class="sy0">,</span> <span class="st0">&quot;max&quot;</span><span class="sy0">=&gt;</span><span class="nu0">1000</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
<span class="nu0">3</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;term&quot;</span><span class="sy0">=&gt;</span><span class="st0">&quot;river+ravensbourne&quot;</span><span class="sy0">,</span> <span class="st0">&quot;max&quot;</span><span class="sy0">=&gt;</span><span class="nu0">1000</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
<span class="nu0">4</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;term&quot;</span><span class="sy0">=&gt;</span><span class="st0">&quot;deptford+market&quot;</span><span class="sy0">,</span> <span class="st0">&quot;max&quot;</span><span class="sy0">=&gt;</span><span class="nu0">1000</span><span class="br0">&#41;</span><br />
<span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="co1">// picking a random term, and then picking a random position for the url</span><br />
<span class="re0">$term_id</span> <span class="sy0">=</span> <a href="http://www.php.net/rand"><span class="kw3">rand</span></a><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span><a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$search_arr</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="re0">$term</span> <span class="sy0">=</span> <span class="re0">$search_arr</span><span class="br0">&#91;</span><span class="re0">$term_id</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&quot;term&quot;</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
<span class="re0">$pos</span> <span class="sy0">=</span> <a href="http://www.php.net/rand"><span class="kw3">rand</span></a><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span><span class="re0">$search_arr</span><span class="br0">&#91;</span><span class="re0">$term_id</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&quot;max&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="re0">$url</span> <span class="sy0">=</span> <span class="st0">&quot;http://boss.yahooapis.com/ysearch/images/v1/&quot;</span> <span class="sy0">.</span> <span class="re0">$term</span> <span class="sy0">.</span> <span class="st0">&quot;?appid=&lt;YOUR_APP_ID&gt;&amp;format=json&amp;count=1&amp;start=&quot;</span> <span class="sy0">.</span> <span class="re0">$pos</span><span class="sy0">;</span></p>
<p><span class="co1">// sendRequest</span><br />
<span class="co1">// note how referer is set manually</span><br />
<span class="re0">$ch</span> <span class="sy0">=</span> <a href="http://www.php.net/curl_init"><span class="kw3">curl_init</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a href="http://www.php.net/curl_setopt"><span class="kw3">curl_setopt</span></a><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_URL<span class="sy0">,</span> <span class="re0">$url</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a href="http://www.php.net/curl_setopt"><span class="kw3">curl_setopt</span></a><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_RETURNTRANSFER<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a href="http://www.php.net/curl_setopt"><span class="kw3">curl_setopt</span></a><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_REFERER<span class="sy0">,</span> <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="re0">$body</span> <span class="sy0">=</span> <a href="http://www.php.net/curl_exec"><span class="kw3">curl_exec</span></a><span class="br0">&#40;</span><span class="re0">$ch</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a href="http://www.php.net/curl_close"><span class="kw3">curl_close</span></a><span class="br0">&#40;</span><span class="re0">$ch</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="co1">// now, process the JSON string</span><br />
<span class="re0">$json</span> <span class="sy0">=</span> <a href="http://www.php.net/json_decode"><span class="kw3">json_decode</span></a><span class="br0">&#40;</span><span class="re0">$body</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="kw1">return</span> <span class="re0">$json</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<span class="re0">$json</span> <span class="sy0">=</span> getLink<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p><span class="co1">// in case we don&#8217;t get any results &#8211; we simply try again</span><br />
<span class="kw1">while</span> <span class="br0">&#40;</span><a href="http://www.php.net/is_null"><span class="kw3">is_null</span></a><span class="br0">&#40;</span><span class="re0">$json</span><span class="sy0">-&gt;</span><span class="me1">ysearchresponse</span><span class="sy0">-&gt;</span><span class="me1">resultset_images</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$json</span> <span class="sy0">=</span> getLink<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="co1">// Using foreach &#8211; but we only get one URL</span><br />
<span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$json</span><span class="sy0">-&gt;</span><span class="me1">ysearchresponse</span><span class="sy0">-&gt;</span><span class="me1">resultset_images</span> <span class="kw1">as</span> <span class="re0">$val</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">echo</span> <span class="re0">$val</span><span class="sy0">-&gt;</span><span class="me1">url</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<span class="sy1">?&gt;</span></div>
</div>
<p><a href="http://blog.gingerlime.com/wp-content/uploads/2010/09/IMG_1514.jpg"><img src="http://blog.gingerlime.com/wp-content/uploads/2010/09/IMG_1514-300x225.jpg" alt="" title="code" width="300" height="225" style="border: 0pt none; float:right; padding-left:20px; padding-bottom:50px" /></a></p>
<p>The last part took me probably the longest to work out. Primarily because (very much like php), I have no clue when it comes to javascript and all that XMLHTTPRequest stuff. The code below kinda works, but probably not in IE, and it&#8217;s probably pretty lame too. What it simply does is pull a new url for an image from the php script above every 10 seconds. It&#8217;s <em>supposed</em> to detect an invalid image and then reload another, but I&#8217;m not entirely sure it works actually.</p>
<div class="codesnip-container" >
<div class="javascript codesnip"><span class="sy0">&lt;</span>html<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;</span>head<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;</span>script language<span class="sy0">=</span><span class="st0">&quot;JavaScript&quot;</span><span class="sy0">&gt;</span></p>
<p><span class="co1">// I&#8217;m using two images, so if there&#8217;s an error on one, I can quickly swap it with another. I&#8217;m not even sure it works</span><br />
<span class="kw2">var</span> img1<span class="sy0">=</span><span class="kw2">null</span><span class="sy0">;</span><br />
<span class="kw2">var</span> img2<span class="sy0">=</span><span class="kw2">null</span><span class="sy0">;</span><br />
&nbsp;<br />
<span class="co1">// this is the function that gets called on error</span><br />
&nbsp;<span class="kw2">function</span> ImgErr<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; document.<span class="me1">myimage</span>.<span class="me1">src</span> <span class="sy0">=</span> img1<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; img1 <span class="sy0">=</span> img2<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="co1">// this function gets called every 10 seconds and loads a new image</span><br />
&nbsp;<span class="kw2">function</span> RefreshImage<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">var</span> xhr<span class="sy0">=</span><span class="kw2">null</span><span class="sy0">;</span><br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>img1 <span class="sy0">!=</span> <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;document.<span class="me1">myimage</span>.<span class="me1">src</span> <span class="sy0">=</span> img1<span class="sy0">;</span><br />
&nbsp; &nbsp;img1 <span class="sy0">=</span> img2<span class="sy0">;</span><br />
&nbsp; &nbsp;<span class="kw1">try</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp;xhr <span class="sy0">=</span> <span class="kw2">new</span> XMLHttpRequest<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> <br />
&nbsp; &nbsp;<span class="br0">&#125;</span> <span class="kw1">catch</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp;<span class="kw1">try</span> <span class="br0">&#123;</span> xhr <span class="sy0">=</span> <span class="kw2">new</span> ActiveXObject<span class="br0">&#40;</span><span class="st0">&quot;Msxml2.XMLHTTP&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp;<span class="kw1">catch</span> <span class="br0">&#40;</span>e2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">try</span> <span class="br0">&#123;</span> xhr <span class="sy0">=</span> <span class="kw2">new</span> ActiveXObject<span class="br0">&#40;</span><span class="st0">&quot;Microsoft.XMLHTTP&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">catch</span> <span class="br0">&#40;</span>e<span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; xhr.<span class="me1">onreadystatechange</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp;document.<span class="me1">myimage</span>.<span class="me1">alt</span><span class="sy0">=</span><span class="st0">&quot;Loading&#8230;&quot;</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp;<span class="kw1">if</span><span class="br0">&#40;</span>xhr.<span class="me1">readyState</span> <span class="sy0">==</span> <span class="nu0">4</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>xhr.<span class="kw3">status</span> <span class="sy0">==</span> <span class="nu0">200</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>img1 <span class="sy0">!=</span> <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;document.<span class="me1">myimage</span>.<span class="me1">src</span><span class="sy0">=</span>img1<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;img2 <span class="sy0">=</span> xhr.<span class="me1">responseText</span><span class="sy0">;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span> <br />
&nbsp;<span class="br0">&#125;</span><span class="sy0">;</span> </p>
<p>&nbsp;xhr.<span class="kw3">open</span><span class="br0">&#40;</span><span class="st0">&quot;GET&quot;</span><span class="sy0">,</span> <span class="st0">&quot;editionof1-img.php&quot;</span><span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp;xhr.<span class="me1">send</span><span class="br0">&#40;</span><span class="kw2">null</span><span class="br0">&#41;</span><span class="sy0">;</span> <br />
<span class="br0">&#125;</span></p>
<p>window.<span class="me1">setInterval</span><span class="br0">&#40;</span><span class="st0">&#8216;RefreshImage()&#8217;</span><span class="sy0">,</span> <span class="nu0">10000</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">&lt;/</span>script<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;/</span>head<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;</span>body<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;</span>img src<span class="sy0">=</span><span class="st0">&quot;http://editionof1.org/Editionof1.org/image-1_files/droppedImage_1.jpg&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;myimage&quot;</span> width<span class="sy0">=</span><span class="st0">&quot;1497&quot;</span> height<span class="sy0">=</span><span class="st0">&quot;1342&quot;</span> <span class="kw3">onerror</span><span class="sy0">=</span><span class="st0">&quot;ImgErr()&quot;</span><span class="sy0">&gt;</span><br />
<span class="sy0">&lt;</span>script<span class="sy0">&gt;</span><br />
RefreshImage<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">&lt;/</span>script<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;/</span>body<span class="sy0">&gt;</span><br />
<span class="sy0">&lt;/</span>html<span class="sy0">&gt;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/2nd-edition-of-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Once upon a time</title>
		<link>http://blog.gingerlime.com/once-upon-a-time</link>
		<comments>http://blog.gingerlime.com/once-upon-a-time#comments</comments>
		<pubDate>Wed, 14 Jul 2010 22:47:54 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=175</guid>
		<description><![CDATA[One-Time-Passwords always fascinated me. Long long time ago in a land far far away I suddenly had this idea. The idea was simple and in today&#8217;s terms pretty common, perhaps trivial. One-Time-Password without the need for an extra token. After the user keys in their username and password, they get sent a random password via [...]]]></description>
			<content:encoded><![CDATA[<p>One-Time-Passwords always fascinated me. Long long time ago in a land far far away I suddenly had this idea. The idea was simple and in today&#8217;s terms pretty common, perhaps trivial. One-Time-Password without the need for an extra token. After the user keys in their username and password, they get sent a random password via SMS. Ten years ago there wasn&#8217;t anything that did that. I created a basic RADIUS implementation with support for different SMS gateways, all in Java. Sadly however, with no funding, no clue how to turn it into a business, and just finishing my computer science degree, it had to be abandoned for an easier day job.</p>
<p>I was recently pulled into looking at two-factor-authentication (2FA) solutions. I used SecurID at a previous job, and know of several solutions in this area. I was quite pleased to discover many soft-token solutions working on mobile phones (iphone, blackberry, HTC, Nokia) and USB-based ideas like <a href="http://www.yubico.com/products/yubikey/">Yubikey</a>. I was even more pleased to discover open source initiatives in this area, and <a href="http://www.openauthentication.org/">OATH</a> <a href="http://en.wikipedia.org/wiki/HOTP">HOTP</a> in particular.<br />
<span id="more-175"></span><br />
HMAC-based One-Time-Password (HOTP) is reasonably simple to implement. It&#8217;s <a href="http://tools.ietf.org/html/rfc4226">open</a>, free and secure. Perhaps not militrary-grade security, but pretty good security nevertheless. I also must have found half a dozen free HOTP apps for my iphone (I&#8217;m using <a href="http://code.google.com/p/oathtoken/">oathtoken</a>), and it seems like there are apps for almost any phone. When coming to implement it on the server though, I felt a little disappointed. There are a couple of pam modules for linux (<a href="http://www.nongnu.org/hotp-toolkit/">HOTP toolkit</a> and <a href="http://barada.sourceforge.net/">Barada</a>), but neither seem very stable or widely used. </p>
<p>What about python implementations then?? I was genuinely surprised there were virtually none. I found <a href="http://code.google.com/p/pynotp/">one</a>, but it seemed rather specific to the Hebrew University and slightly complex. Or maybe I was too lazy to work out what it actually did&#8230;</p>
<p>So I then decided to write my own. It&#8217;s a very basic implementation, and by no means &#8216;production ready&#8217;, but it seems to work. I tested it against the test vectors on the <a href="http://tools.ietf.org/html/rfc4226">rfc</a>, and with my oathtoken iphone app, and it seems to match. I even implemented <a href="http://tools.ietf.org/html/draft-mraihi-totp-timebased-00">TOTP</a>, a time-based variant instead of counter based &#8211; and that worked too!</p>
<div class="codesnip-container" >
<div class="python codesnip"><span class="co1">#!/usr/bin/env python</span></p>
<p><span class="kw1">import</span> <span class="kw3">hmac</span><br />
<span class="kw1">import</span> <span class="kw3">sha</span><br />
<span class="kw1">import</span> <span class="kw3">struct</span><br />
<span class="kw1">import</span> <span class="kw3">array</span><br />
<span class="kw1">import</span> <span class="kw3">time</span><br />
&nbsp; &nbsp; <br />
<span class="kw1">def</span> HOTP<span class="br0">&#40;</span>K, C, digits=<span class="nu0">6</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; C_bytes = _long_to_byte_array<span class="br0">&#40;</span>C<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="co1">#C_bytes = _hex_to_byte_array(str(hex(C)).lstrip(&quot;0x&quot;).rstrip(&quot;L&quot;))</span><br />
&nbsp; &nbsp; hmac_sha1 = <span class="kw3">hmac</span>.<span class="kw3">new</span><span class="br0">&#40;</span>key=K, msg=C_bytes, digestmod=<span class="kw3">sha</span><span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> Truncate<span class="br0">&#40;</span>hmac_sha1<span class="br0">&#41;</span><span class="br0">&#91;</span>-digits:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; <br />
<span class="kw1">def</span> TOTP<span class="br0">&#40;</span>K, digits=<span class="nu0">6</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; C = <span class="kw2">long</span><span class="br0">&#40;</span><span class="kw3">time</span>.<span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span>/<span class="nu0">30</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> HOTP<span class="br0">&#40;</span>K, C, digits=digits<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
<span class="kw1">def</span> _long_to_byte_array<span class="br0">&#40;</span>long_num<span class="br0">&#41;</span>: &nbsp; &nbsp;<br />
&nbsp; &nbsp; byte_array = <span class="kw3">array</span>.<span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#8216;B&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">reversed</span><span class="br0">&#40;</span><span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">0</span>,<span class="nu0">8</span><span class="br0">&#41;</span><span class="br0">&#41;</span>: &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; byte_array.<span class="me1">insert</span><span class="br0">&#40;</span><span class="nu0">0</span>,long_num <span class="sy0">&amp;</span> 0xff<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; long_num <span class="sy0">&gt;&gt;</span>= <span class="nu0">8</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> byte_array<br />
&nbsp; &nbsp; <br />
<span class="kw1">def</span> _hex_to_byte_array<span class="br0">&#40;</span>hexStr<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;&quot;<br />
&nbsp; &nbsp; Source: http://code.activestate.com/recipes/510399-byte-to-hex-and-hex-to-byte-string-conversion/<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; Convert a string hex byte values into a byte string. The Hex Byte values may<br />
&nbsp; &nbsp; or may not be space separated.<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="co1"># The list comprehension implementation is fractionally slower in this case &nbsp; &nbsp;</span><br />
&nbsp; &nbsp; <span class="co1">#</span><br />
&nbsp; &nbsp; <span class="co1"># &nbsp; &nbsp;hexStr = &#8221;.join( hexStr.split(&quot; &quot;) )</span><br />
&nbsp; &nbsp; <span class="co1"># &nbsp; &nbsp;return &#8221;.join( [&quot;%c&quot; % chr( int ( hexStr[i:i+2],16 ) ) \</span><br />
&nbsp; &nbsp; <span class="co1"># &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i in range(0, len( hexStr ), 2) ] )</span><br />
&nbsp;<br />
&nbsp; &nbsp; <span class="kw3">bytes</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; hexStr = <span class="st0">&#8221;</span>.<span class="me1">join</span><span class="br0">&#40;</span> hexStr.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="kw2">len</span><span class="br0">&#40;</span>hexStr<span class="br0">&#41;</span>, <span class="nu0">2</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">bytes</span>.<span class="me1">append</span><span class="br0">&#40;</span> <span class="kw2">chr</span><span class="br0">&#40;</span> <span class="kw2">int</span> <span class="br0">&#40;</span>hexStr<span class="br0">&#91;</span>i:i+<span class="nu0">2</span><span class="br0">&#93;</span>, <span class="nu0">16</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&#8221;</span>.<span class="me1">join</span><span class="br0">&#40;</span> <span class="kw3">bytes</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
<span class="kw1">def</span> Truncate<span class="br0">&#40;</span>hmac_sha1<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; offset = <span class="kw2">int</span><span class="br0">&#40;</span>hmac_sha1<span class="br0">&#91;</span>-<span class="nu0">1</span><span class="br0">&#93;</span>,<span class="nu0">16</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; binary = <span class="kw2">int</span><span class="br0">&#40;</span>hmac_sha1<span class="br0">&#91;</span>offset<span class="sy0">*</span><span class="nu0">2</span> : offset<span class="sy0">*</span><span class="nu0">2</span>+<span class="nu0">8</span><span class="br0">&#93;</span>,<span class="nu0">16</span><span class="br0">&#41;</span> &nbsp;<span class="sy0">&amp;</span> 0x7fffffff<br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">str</span><span class="br0">&#40;</span>binary<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
<span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="co1"># some test vectors</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">0</span>,<span class="nu0">10</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> HOTP<span class="br0">&#40;</span><span class="st0">&#8217;12345678901234567890&#8242;</span>,i<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> HOTP<span class="br0">&#40;</span>_hex_to_byte_array<span class="br0">&#40;</span><span class="st0">&#8217;3132333435363738393031323334353637383930&#8242;</span><span class="br0">&#41;</span>,i<span class="br0">&#41;</span> </p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> TOTP<span class="br0">&#40;</span>_hex_to_byte_array<span class="br0">&#40;</span><span class="st0">&#8217;3132333435363738393031323334353637383930&#8242;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/once-upon-a-time/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iphone running late</title>
		<link>http://blog.gingerlime.com/iphone-running-late</link>
		<comments>http://blog.gingerlime.com/iphone-running-late#comments</comments>
		<pubDate>Wed, 23 Jun 2010 20:49:16 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=169</guid>
		<description><![CDATA[I recently noticed my iphone clock wasn&#8217;t accurate. I&#8217;m not exactly sure why. It was only a few minutes behind, but it still annoyed me. Why couldn&#8217;t my iphone sync its time with an internet time server?? I know it is supposed to sync with my mobile network operator, but I think mine doesn&#8217;t sync&#8230; [...]]]></description>
			<content:encoded><![CDATA[<p>I recently noticed my iphone clock wasn&#8217;t accurate. I&#8217;m not exactly sure why. It was only a few minutes behind, but it still annoyed me. Why couldn&#8217;t my iphone sync its time with an internet time server?? I know it is supposed to sync with my mobile network operator, but I think mine doesn&#8217;t sync&#8230; Maybe it&#8217;s my operator?</p>
<p>For jailbroken iphones, there&#8217;s a neat app on cydia called <a href="http://iwatcher.net/2010/06/11/ntpdate-1-0/">NTPDate</a>. It&#8217;s a great app and I recommend installing it. All you need is specify the ntp server, and click &#8216;set&#8217; and it will sync your clock for you. However, I wanted to go a step further. I wanted my iphone to sync itself automatically for me, using a cron job. Well, not quite using cron, but it can be done automatically.<br />
<span id="more-169"></span><br />
Here&#8217;s a quick step by step:</p>
<p>1. Install NTPDate from cydia.<br />
2. SSH to your iphone and create a shell script in /usr/bin (or SCP it to your iphone), lets call it <strong>/usr/bin/time_sync.sh</strong></p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p><span class="sy0">/</span>Applications<span class="sy0">/</span>NTPdate.app<span class="sy0">/</span>bin<span class="sy0">/</span>ntpdate ntp.exnet.com</div>
</div>
<p>Notice I used an ntp server in the UK (ntp.exnet.com). You can use any ntp server.</p>
<p>3. Create a new plist file in /Library/LaunchDaemons (or SCP it to your iphone), lets call it <strong>/Library/LaunchDaemons/com.test.synctime.plist</strong></p>
<div class="codesnip-container" >
<div class="xml codesnip"><span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;UTF-8&quot;</span><span class="re2">?&gt;</span></span><br />
<span class="sc0">&lt;!DOCTYPE plist PUBLIC &quot;-//Apple Computer//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;</span><br />
<span class="sc3"><span class="re1">&lt;plist</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span><span class="re2">&gt;</span></span></p>
<p><span class="sc3"><span class="re1">&lt;dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Label<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;string<span class="re2">&gt;</span></span></span>test.synctime<span class="sc3"><span class="re1">&lt;/string<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>OnDemand<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;true</span><span class="re2">/&gt;</span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Program<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;string<span class="re2">&gt;</span></span></span>/usr/bin/time_sync.sh<span class="sc3"><span class="re1">&lt;/string<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>StartCalendarInterval<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Minute<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;integer<span class="re2">&gt;</span></span></span>7<span class="sc3"><span class="re1">&lt;/integer<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/dict<span class="re2">&gt;</span></span></span></p>
<p><span class="sc3"><span class="re1">&lt;/plist<span class="re2">&gt;</span></span></span></div>
</div>
<p>This plist is set to run every hour, at 7 minutes past the hour</p>
<p>4. install the plist file</p>
<div class="codesnip-container" >
<div class="bash codesnip">user1s-iPhone: root<span class="co0"># launchctl load /Library/LaunchDaemons/com.test.synctime.plist</span></div>
</div>
<p>Job done.</p>
<p>I don&#8217;t know what happens if your phone&#8217;s time is actually ahead, the job might run several times and keep moving the time&#8230; Try at your own risk.</p>
<p>Update: I realised as soon as I plugged my iphone to my mac, it synchornised its time with it. Maybe that&#8217;s why it was drifting&#8230; I left this automatic sync there anyway though.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/iphone-running-late/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iphone asterisk sync</title>
		<link>http://blog.gingerlime.com/iphone-asterisk-sync</link>
		<comments>http://blog.gingerlime.com/iphone-asterisk-sync#comments</comments>
		<pubDate>Sun, 18 Apr 2010 22:32:44 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=123</guid>
		<description><![CDATA[On my last post I described how I get my asterisk box to know the caller name from a csv data file. The thing is, my address book keeps changing on my iphone. People change their phone numbers, I meet new people (can you believe it? I don&#8217;t let it happen too often though)&#8230; I [...]]]></description>
			<content:encoded><![CDATA[<p>On my <a href="http://blog.gingerlime.com/whos-calling">last post</a> I described how I get my asterisk box to know the caller name from a csv data file. The thing is, my address book keeps changing on my iphone. People change their phone numbers, I meet new people (can you believe it? I don&#8217;t let it happen too often though)&#8230; I wanted to be able to sync it automatically to my asterisk. This synchronisation also doubles up as a backup for my address book.<br />
<span id="more-123"></span><br />
This method works on jailbroken iphone version 3. You&#8217;d need to setup and enable ssh access to your iphone. There are many resources on how to do it, like <a href="http://justanotheriphoneblog.com/wordpress/2008/04/01/how-to-connect-to-your-iphone-via-ssh ">this</a> and <a href="http://www.iclarified.com/entry/index.php?enid=3221">this</a>.</p>
<p>The process is fairly simple. You can schedule certain tasks or jobs on the iphone. On older version there used to be a cron daemon, but from version 3 &#8211; this is all managed by launchd (the Launch Daemon). First lets create a script that syncs the address book file (AddressBook.sqlitedb) to a remote host. We&#8217;ll call it <em>address_sync.sh</em></p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p>rsync <span class="re5">-e</span> <span class="kw2">ssh</span> <span class="sy0">/</span>private<span class="sy0">/</span>var<span class="sy0">/</span>mobile<span class="sy0">/</span>Library<span class="sy0">/</span>AddressBook<span class="sy0">/</span>AddressBook.sqlitedb iphone<span class="sy0">@</span>remote.server:<span class="sy0">/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span></div>
</div>
<p>I&#8217;m using a dedicated user called <em>iphone</em> on the remote server, and the script uses rsync over ssh &#8211; it will only use a fraction of the bandwidth to transfer the differences between the files (if any). You can use <em>scp</em> instead if you wish.</p>
<p>Trying to run the script, it would prompt us for a password. We don&#8217;t want to use a password because it must be run automatically, so we should set up ssh-key access.</p>
<p>This is a two-part process. First part, on the iphone itself. ssh to your iphone as root and use these commands:</p>
<div class="codesnip-container" >
<div class="bash codesnip">user1s-iPhone:~ root<span class="co0"># cd ~/.ssh/</span><br />
user1s-iPhone:~<span class="sy0">/</span>.ssh root<span class="co0"># ssh-keygen -b 1024 -t rsa</span><br />
Generating public<span class="sy0">/</span>private rsa key pair.<br />
Enter <span class="kw2">file</span> <span class="kw1">in</span> <span class="kw2">which</span> to save the key <span class="br0">&#40;</span><span class="sy0">/</span>var<span class="sy0">/</span>root<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa<span class="br0">&#41;</span>: <br />
Enter passphrase <span class="br0">&#40;</span>empty <span class="kw1">for</span> no passphrase<span class="br0">&#41;</span>: <br />
Enter same passphrase again: <br />
Your identification has been saved <span class="kw1">in</span> <span class="sy0">/</span>var<span class="sy0">/</span>root<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa.<br />
Your public key has been saved <span class="kw1">in</span> <span class="sy0">/</span>var<span class="sy0">/</span>root<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa.pub.</div>
</div>
<p>Note I used an empty passphrase. Now you&#8217;d need to store the contents of id_rsa.pub file (use scp/winscp or simply copy&#038;paste from the terminal).</p>
<p>Go to the remote server we want to allow our iphone key-based access to and add the public key to the authorized_keys file (replace with the contents of your id_rsa.pub file)</p>
<div class="codesnip-container" >
<div class="bash codesnip">root<span class="sy0">@</span>server:~<span class="co0"># cd /home/iphone/.ssh</span><br />
root<span class="sy0">@</span>server:<span class="sy0">/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span>.ssh<span class="co0"># echo &quot;[contents of the id_rsa.pub]&quot; &gt;&gt;authorized_keys</span></div>
</div>
<p>Test the connection from your iphone:</p>
<div class="codesnip-container" >user1s-iPhone:~/.ssh root# ssh remote.server<br />
The authenticity of host &#8216;remote.server (1.2.3.4)&#8217; can&#8217;t be established.<br />
RSA key fingerprint is 0c:aa:24:51:2b:61:0f:3e:f2:55:11:ab:a2:e4:61:21.<br />
Are you sure you want to continue connecting (yes/no)? yes</div>
<p>All set. Try running the <em>address_sync.sh</em> and check that it copied the file. It should not prompt for password. Put this script under /usr/local/bin</p>
<p>The next part is to schedule this copy to run automatically. In my case, I have decided to run it daily at 1pm. I&#8217;ve followed the excellent post about iphone 3 scheduling <a href="http://blog.mbgeek.com/2008/08/scheduled-jobs-in-iphone/">here</a> and created another file called <em>com.test.syncjob.plist</em>:</p>
<div class="codesnip-container" >
<div class="xml codesnip"><span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;UTF-8&quot;</span><span class="re2">&gt;</span></span><br />
<span class="sc0">&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;</span><br />
<span class="sc3"><span class="re1">&lt;plist</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span><span class="re2">&gt;</span></span><br />
<span class="sc3"><span class="re1">&lt;dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Label<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;string<span class="re2">&gt;</span></span></span>test.syncjob<span class="sc3"><span class="re1">&lt;/string<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>OnDemand<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;true</span><span class="re2">/&gt;</span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Program<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;string<span class="re2">&gt;</span></span></span>/usr/local/bin/address_sync.sh<span class="sc3"><span class="re1">&lt;/string<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>StartCalendarInterval<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Hour<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;integer<span class="re2">&gt;</span></span></span>13<span class="sc3"><span class="re1">&lt;/integer<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;key<span class="re2">&gt;</span></span></span>Minute<span class="sc3"><span class="re1">&lt;/key<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;integer<span class="re2">&gt;</span></span></span>0<span class="sc3"><span class="re1">&lt;/integer<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/dict<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/plist<span class="re2">&gt;</span></span></span></div>
</div>
<p>Copy this file to /Library/LaunchDaemons on your iphone, and run this command on your iphone:</p>
<div class="codesnip-container" >
<div class="bash codesnip">user1s-iPhone:~ root<span class="co0"># launchctl load /Library/LaunchDaemons/com.test.syncjob.plist</span></div>
</div>
<p>All done. Now every day at 1pm, my iphone automatically syncs my address book to my server. That&#8217;s great for backups. How do I convert the AddressBook.sqlitedb file to csv for my asterisk box?</p>
<p>I created a cron job on the server that does it automatically. It&#8217;s comprised of a shell script and some python code:</p>
<p><em>export-csv.sh:</em></p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p><span class="co0"># converts the sqlite database to csv</span><br />
sqlite3 <span class="re5">-csv</span> <span class="sy0">/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span>AddressBook.sqlitedb <span class="st0">&quot;SELECT First, Last, ABMultiValue.value FROM ABPerson, ABMultiValue WHERE ROWID=record_id;&quot;</span> <span class="sy0">&gt;/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span>AddressBook.csv</p>
<p><span class="co0"># converts the csv to a more asterisk-friendly format using a python script (see below)</span><br />
<span class="co0"># also removes any email addresses. I only care about phone numbers</span><br />
<span class="sy0">/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span>convert-csv.py <span class="sy0">/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span>AddressBook.csv <span class="sy0">|</span><span class="kw2">grep</span> <span class="re5">-v</span> <span class="sy0">@</span> <span class="sy0">&gt;/</span>home<span class="sy0">/</span>iphone<span class="sy0">/</span>myPhoneBook.csv</div>
</div>
<p>Note that I could easily pipe data instead of saving it into files, but I wanted to have a csv file anyway.</p>
<p><em>convert-csv.py:</em></p>
<div class="codesnip-container" >
<div class="python codesnip"><span class="co1">#!/usr/bin/env python</span></p>
<p><span class="kw1">import</span> <span class="kw3">csv</span><br />
<span class="kw1">from</span> <span class="kw3">sys</span> <span class="kw1">import</span> argv</p>
<p><span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>argv<span class="br0">&#41;</span> <span class="sy0">&lt;</span>= <span class="nu0">1</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;usage: %s &lt;filename&gt;&quot;</span> <span class="sy0">%</span> argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; exit<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
fd = <span class="kw2">file</span><span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="kw1">for</span> lines <span class="kw1">in</span> <span class="kw3">csv</span>.<span class="me1">reader</span><span class="br0">&#40;</span>fd<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; full_name = <span class="st0">&quot;%s %s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>lines<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, lines<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>,%s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>full_name.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, lines<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span>,<span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/iphone-asterisk-sync/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guilty Pleasures</title>
		<link>http://blog.gingerlime.com/guilty-pleasures</link>
		<comments>http://blog.gingerlime.com/guilty-pleasures#comments</comments>
		<pubDate>Wed, 25 Mar 2009 14:23:02 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=62</guid>
		<description><![CDATA[Perhaps yet another misleading title for this post, but bear with me. When I was a child we used to play outside a lot. I always remember the neighbours complaining if we made too much noise. Such is life. There was one period of time that I knew I would get in trouble though. We [...]]]></description>
			<content:encoded><![CDATA[<p>Perhaps yet another misleading title for this post, but bear with me. When I was a child we used to play outside a lot. I always remember the neighbours complaining if we made too much noise. Such is life. There was one period of time that I knew I would get in trouble though. We would get told off big time!! When?? Every day between 2 and 4 in the afternoon. There was even a sign in big red letters telling us all to keep quiet at &#8216;rest time&#8217; (loosely translated). There was no sign about making noise after 11pm, but there was one for the afternoon nap. It was THAT important.<br />
<br/>These days seem long gone now. Does anybody have time for an afternoon nap?? I certainly don&#8217;t recall seeing any such signs around.<br />
<span id="more-62"></span><br />
I just LOVE an afternoon nap. It&#8217;s one of modern life&#8217;s guiltiest pleasures. You just know you have things to do, and you&#8217;re not supposed to just switch off, but you slip into bed, close the door, pull the blinds down, and even 30 minutes get you feeling like a whole new person. Oh the pure joy.</p>
<p><br/><br />
Alas, even with no kids playing around (do kids play outside anyway??), there is always an odd telephone call to wake you up and make you feel even worse (either from guilt or just for being woken up). This can also happen in the morning. Well, for some people it&#8217;s late morning or even early afternoon, but I do like to stay in bed late and have a good lie-in.</p>
<p>So what&#8217;s the problem?? I can easily unplug my phones. Well, it&#8217;s a no brainer with the mobile. The only time it&#8217;s switched off is when I&#8217;m asleep anyway. But the landline?? I don&#8217;t get many people to call me at home these days, but particularly if my mobile is switched off, people (my mum is the worst offender) will make an effort and check that I&#8217;m alive. I know I can unplug it, and on my fancy Asterisk box I can even set it to Do Not Disturb by simply calling *78. But I usually forget about it, or forget to plug it in again, and frankly it&#8217;s a hassle.</p>
<p><br/><br />
What I want to do is switch the ringing off as soon as I switch off my mobile phone. Have those two aware of each other somehow. How??</p>
<p>Well, this is not a solution for everybody, but it works for me. The idea was taken from <a href="http://nerdvittles.com/?p=185">Nerd Vittles</a> but modified for my needs and even improved it. No need to install bluetooth software on my Asterisk box. I already have it on my Ubuntu at home. Most bluetooth dongles are pretty much plug&#038;play these days with most Linux desktop distros.</p>
<p>Who is this solution for? or what do you need?</p>
<ul>
<li><a href="http://www.asterisk.org/">Asterisk</a> &#8211; the best open source VOIP system</li>
<li>ssh access to your asterisk (with ssh keys to avoid password prompts)</li>
<li>Voip Phone</li>
<li>bluetooth enabled on your home Linux box (mine is Ubuntu 8.04)</li>
<li><a href="http://blueproximity.sourceforge.net/index.html">Blueproximity</a></li>
<li>A bluetooth enabled mobile phone</li>
</ul>
<p>So what&#8217;s going on and how??</p>
<p>If you&#8217;re familiar with Asterisk, ssh and some basic scripting, you&#8217;ll have no problems following it. I&#8217;m not going to spell out each step, but feel free to ask if you need.</p>
<p>The idea is very simple. <a href="http://blueproximity.sourceforge.net/index.html">Blueproximity</a> is meant to be used to lock/unlock your PC when you&#8217;re close or far from it, based on signal from your bluetooth phone. It&#8217;s extensible enough to launch any script you choose, so I simply configured it so when I&#8217;m at home &#8211; my bluetooth phone is within a reasonable proximity &#8211; it launches a script to enable my home phone to ring. When I&#8217;m out of reach (mobile or bluetooth is off) &#8211; it automatically redirects calls to my home phone to my voicemail.</p>
<p><a href="http://nerdvittles.com/?p=185">Nerd Vittles</a>&#8216;s set-up was to forward calls to your mobile. You can do that too. However, the biggest downsides of this solution is that you need the bluetooth installed on your Asterisk server. Mine is hosted in Germany, so just a little too far to detect my mobile&#8217;s bluetooth signal.</p>
<p>My desktop however, is more than capable to cover the entire flat.</p>
<p>So I created a little script on my remote Asterisk box which changes the dialplan to either forward direct to voicemail, or to my home extension:</p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p><span class="co0"># DND On &#8211; Do Not Disturb</span></p>
<p>asterisk <span class="re5">-rx</span> <span class="st0">&quot;dialplan add extension 1234,1,Voicemail(u1234@default) into inbound replace&quot;</span></div>
</div>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p><span class="co0"># DND Off &#8211; Ring my phone</span></p>
<p>asterisk <span class="re5">-rx</span> <span class="st0">&quot;dialplan add extension 1234,1,Dial(SIP/1234,20,trj) into inbound replace&quot;</span></div>
</div>
<p>I then created two matching scripts on my home desktop which simply call those scripts remotely:</p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p><span class="kw2">ssh</span> my.asterisk.box <span class="st0">&quot;dnd-on&quot;</span></div>
</div>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span></p>
<p><span class="kw2">ssh</span> my.asterisk.box <span class="st0">&quot;dnd-off&quot;</span></div>
</div>
<p>I obviously use <a href="http://pkeck.myweb.uga.edu/ssh/">ssh keys</a> to authenticate to my asterisk box without a password.</p>
<p>Now all is left is to set up Blueproximity to launch those scripts instead of the default gnome-screensaver-command</p>
<p>I set the lock proximity in Blueproximity to the max and the unlock to slightly lower.<br />
<br/>All I have to do to have some quiet time and enjoy my guilty pleasure is simply switch off my mobile.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/guilty-pleasures/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GoDaddy taking european domains hostage prior to expiration</title>
		<link>http://blog.gingerlime.com/godaddy-taking-european-domains-hostage-prior-to-expiration</link>
		<comments>http://blog.gingerlime.com/godaddy-taking-european-domains-hostage-prior-to-expiration#comments</comments>
		<pubDate>Mon, 23 Feb 2009 02:17:50 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=52</guid>
		<description><![CDATA[This is something I never thought would concern me. All those domain ownership issues, I thought, were with people who just aren&#8217;t organised enough to renew their domains, forget their passwords, or pick domains that others try to steal. I&#8217;m currently managing a couple of .DE and one .CO.UK domains on Godaddy. The .co.uk domain [...]]]></description>
			<content:encoded><![CDATA[<p>This is something I never thought would concern me. All those domain ownership issues, I thought, were with people who just aren&#8217;t organised enough to renew their domains, forget their passwords, or pick domains that others try to steal.</p>
<p>I&#8217;m currently managing a couple of .DE and one .CO.UK domains on Godaddy. The .co.uk domain was bought for a fairly long period, so no problems there, but recently, both the .de domains were up for renewal. I received a couple of email reminders from GoDaddy, but when I logged into my account I noticed they are only due to expire on 26th March. More than a month away. On the last email I received on the 20th, I decided it&#8217;s probably time to renew, so clicked on the link and was getting my credit card ready.</p>
<p>To my surprise, the GoDaddy domain portal did not allow me to renew them, and marked them as &#8216;pending expiration&#8217;. hmmm&#8230; weird. Oh well, I emailed GoDaddy and asked to renew, not even worrying too much. Maybe a system glitch of some sort.<br />
<span id="more-52"></span></p>
<p>When an email arrived in response, it said that all .co.uk (yeah, this is not a typo, even though I emailed them about 2 .de domains) have to be renewed on the 20th of the month prior to expiration. Very strange. I pointed out to GoDaddy that these were .de domains and even so, why can&#8217;t they allow you to renew over their own website??</p>
<p>It was then, that things were beginning to look suspicious. I tried to access both those domains, and was shocked to find out I&#8217;m being redirected to a GoDaddy &#8216;free parking&#8217; page &#8211; i.e. a page full of GoDaddy ads and links. Not to where it should have led me to obviously.</p>
<p>WHAT?? The domains are still mine. They have not expired, yet GoDaddy simply hijacked them. That can&#8217;t be right. Surely enough. That&#8217;s what GoDaddy did.</p>
<p>Ok. I felt angry, and disappointed and very stupid too. Did I miss an email reminder telling me this is going to happen and I ignored it?? I searched through my emails, and nowhere did it say anything about it. </p>
<p>This is what their initial renewal email said</p>
<div class="codesnip-container" >You have elected that the domain name(s) above renew manually. This means that they WILL EXPIRE if you do not log in to your account and renew them by the expiration date(s) listed.</div>
<p>BY THE EXPIRATION DATE(s) LISTED. The dates listed were 26th March. Not the 20th of February.</p>
<p>Ok, so maybe it&#8217;s on the original Terms and Conditions I must have signed. I searched, and looked, and searched again. Nothing.</p>
<p>Right then, so it&#8217;s probably something the .DE domain TLD forces GoDaddy to do. I trawled through <a href="http://www.denic.de">DENIC</a>. Trying to find a clue. Nope. Nein. Nicht. </p>
<p>I&#8217;ve had numerous emails and a long telephone conversation with GoDaddy support, but they simply wouldn&#8217;t listen. I eventually got to a supervisor who gave me two options:</p>
<p>1. Do nothing, and these domains will expire, but only on the 26th March. Until then they are not going to be released or re-activated.<br />
2. Pay their renewal fees, agree to their terms (which also mean 60 days lock from transferring)</p>
<p>I obviously had no alternative but to pay. The fees were reasonable. At least no nasty &#8216;re-activation fee&#8217;. I didn&#8217;t mind paying the renewal fees anyway and in the first place. But why hijack my domains??</p>
<p>As of now, nearly 24 hours after paying, and after another couple of emails to their support, my domains are still locked and redirected to a landing page.</p>
<p>I then came across <a href="http://princesimon.wordpress.com/2008/12/30/godaddycoms-shady-and-unethical-domain-names-renewal-process/">this post</a> by <a href="http://princesimon.wordpress.com/about/">Simon Kapenda</a>. Looks like he&#8217;s in a similar position to mine. There was another similar post, mostly with .co.uk domains <a href="http://codingforums.com/showthread.php?t=117457">here</a>, but not much more I could find.</p>
<p>If you&#8217;ve been affected please let me know. Surely there&#8217;s something that can be done to complain against such practice.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/godaddy-taking-european-domains-hostage-prior-to-expiration/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Postcode, Barcode and python code</title>
		<link>http://blog.gingerlime.com/postcode-barcode-and-python-code</link>
		<comments>http://blog.gingerlime.com/postcode-barcode-and-python-code#comments</comments>
		<pubDate>Fri, 30 Jan 2009 15:22:14 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=41</guid>
		<description><![CDATA[I&#8217;ve had a strange thing happening a while ago. I sent a CD in a padded envelope to someone, and it was returned to me. Well, it didn&#8217;t look like it was returned, more like they actually delivered it to me instead of to the person I sent it to. Then I noticed something. I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had a strange thing happening a while ago. I sent a CD in a padded envelope to someone, and it was returned to me. Well, it didn&#8217;t look like it was returned, more like they actually delivered it to me instead of to the person I sent it to.</p>
<p>Then I noticed something. I was re-using an old envelope. For environmental reasons of course (read: being so tight-assed, saving money on padded envelopes). I did write the destination address on the right side, so my address was nowhere on the envelope. What was left there however was this tiny printed barcode used by the previous sender with my address.<br />
<span id="more-41"></span><br />
So it occurred to me, the postoffice didn&#8217;t even bother reading the address I put there, it scanned the little barcode instead. </p>
<p>Neat. So maybe I could print those barcodes and make sure my letters get to the right destination.</p>
<p>A little googling brought me to this nice <a href="http://www.bluetang.co.uk/btwebsystems/utilities/postbarcode/Default.aspx">web page</a> you can put your postcode and it generates a string for you, which if you use in a word processor with a special barcode font (also available for <a href="http://www.bluetang.co.uk/btwebsystems/utilities/postbarcode/Custcode.ttf">download</a> there), you can print out yourself. </p>
<p>That&#8217;s nice. What I couldn&#8217;t work out however, is how the postcode checksum is calculated. The <a href="http://www.bluetang.co.uk/btwebsystems/utilities/postbarcode/Default.aspx">website</a> was nice enough to do it for you, but what happens if it&#8217;s unavailable or goes down??</p>
<p>My good friend Dan, after noticing I used those fancy barcodes on a letter I sent him, managed to find more information about the <a href="http://www.mailsorttechnical.com/docs/mug_2008/MUG_2008_08_Mailsort_700.pdf">checksum algorithm</a>, and was even kind enough to write some perl code that runs it. </p>
<p>When Dan shares his code I&#8217;ll link to it, but meanwhile, and just to practice with some python coding, I wrote my own python code to do the same thing (but obviously in a much nicer way than perl):</p>
<div class="codesnip-container" >
<div class="python codesnip"><span class="co1">#!/usr/bin/env python</span></p>
<p><span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">re</span></p>
<p><span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="sy0">&lt;</span><span class="nu0">2</span>:<br />
&nbsp; <span class="kw1">print</span> <span class="st0">&quot;&quot;&quot;<br />
&nbsp; &nbsp; Usage: Postcode.py &lt;PostCode&gt; [&lt;Suffix&gt;]<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &lt;PostCode&gt; must appear with no spaces, e.g. SN34RD, case insensitive<br />
&nbsp; &nbsp; &lt;Suffix&gt; is optional and set by default to 9Z (if you don&#8217;t know it, don&#8217;t use it)<br />
&nbsp; &quot;&quot;&quot;</span><br />
&nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>Suffix = <span class="st0">&#8217;9Z&#8217;</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="sy0">&gt;</span><span class="nu0">2</span>:<br />
&nbsp; Suffix = <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>.<span class="me1">upper</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>Suffix<span class="br0">&#41;</span><span class="sy0">!</span>=<span class="nu0">2</span>:<br />
&nbsp; <span class="kw1">print</span> <span class="st0">&quot;&quot;&quot;<br />
&nbsp; Suffix or postcode incorrect. <br />
&nbsp; &nbsp;Please use postcodes without spaces or enclosed in &quot;&quot;<br />
&nbsp; &nbsp;Suffix must be 2 characters (or blank to use 9Z) <br />
&nbsp; &quot;&quot;&quot;</span><br />
&nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Check for correctness of postcode. Regular expression found at http://regexlib.com/REDetails.aspx?regexp_id=260</span><br />
<span class="co1"># (notice &#8211; not at top of the page, but on one of the bottom comments) &nbsp;</span><br />
<span class="kw1">if</span> <span class="kw1">not</span> <span class="kw3">re</span>.<span class="me1">match</span><span class="br0">&#40;</span><span class="st0">&quot;^(([A-PR-UWYZ]{1,2}[0-9]{1,2}[ABEHJMNPRVWXY]?)<span class="es0">\s</span>?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)<span class="es0">\s</span>?(0AA))$&quot;</span>, <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">upper</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; <span class="kw1">print</span> <span class="st0">&quot;Postcode incorrect. Please use correct UK postcodes and either without spaces or enclosed in <span class="es0">\&quot;</span><span class="es0">\&quot;</span>&quot;</span><br />
&nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <br />
Postcode = <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">upper</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&#8216; &#8216;</span>,<span class="st0">&#8221;</span><span class="br0">&#41;</span> + Suffix</p>
<p><span class="co1"># Matrix as it appears on the PDF guide. Note arrays are referenced from 0..5</span><br />
PostCodeMatrix = <span class="br0">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span><span class="st0">&#8217;0&#8242;</span>,<span class="st0">&#8217;1&#8242;</span>,<span class="st0">&#8217;2&#8242;</span>,<span class="st0">&#8217;3&#8242;</span>,<span class="st0">&#8217;4&#8242;</span>,<span class="st0">&#8217;5&#8242;</span><span class="br0">&#93;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span><span class="st0">&#8217;6&#8242;</span>,<span class="st0">&#8217;7&#8242;</span>,<span class="st0">&#8217;8&#8242;</span>,<span class="st0">&#8217;9&#8242;</span>,<span class="st0">&#8216;A&#8217;</span>,<span class="st0">&#8216;B&#8217;</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span><span class="st0">&#8216;C&#8217;</span>,<span class="st0">&#8216;D&#8217;</span>,<span class="st0">&#8216;E&#8217;</span>,<span class="st0">&#8216;F&#8217;</span>,<span class="st0">&#8216;G&#8217;</span>,<span class="st0">&#8216;H&#8217;</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span><span class="st0">&#8216;I&#8217;</span>,<span class="st0">&#8216;J&#8217;</span>,<span class="st0">&#8216;K&#8217;</span>,<span class="st0">&#8216;L&#8217;</span>,<span class="st0">&#8216;M&#8217;</span>,<span class="st0">&#8216;N&#8217;</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span><span class="st0">&#8216;O&#8217;</span>,<span class="st0">&#8216;P&#8217;</span>,<span class="st0">&#8216;Q&#8217;</span>,<span class="st0">&#8216;R&#8217;</span>,<span class="st0">&#8216;S&#8217;</span>,<span class="st0">&#8216;T&#8217;</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span><span class="st0">&#8216;U&#8217;</span>,<span class="st0">&#8216;V&#8217;</span>,<span class="st0">&#8216;W&#8217;</span>,<span class="st0">&#8216;X&#8217;</span>,<span class="st0">&#8216;Y&#8217;</span>,<span class="st0">&#8216;Z&#8217;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#93;</span></p>
<p><span class="co1"># A &#8216;reverse-lookup&#8217; dictionary for each postcode character</span><br />
PostCodeDict = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
<span class="kw1">for</span> row <span class="kw1">in</span> <span class="kw2">range</span> <span class="br0">&#40;</span><span class="nu0">0</span>,<span class="nu0">6</span><span class="br0">&#41;</span>: &nbsp;<br />
&nbsp; <span class="kw1">for</span> col <span class="kw1">in</span> <span class="kw2">range</span> <span class="br0">&#40;</span><span class="nu0">0</span>,<span class="nu0">6</span><span class="br0">&#41;</span>: &nbsp; &nbsp;<br />
&nbsp; &nbsp; PostCodeDict<span class="br0">&#91;</span><span class="br0">&#40;</span>PostCodeMatrix<span class="br0">&#91;</span>row<span class="br0">&#93;</span><span class="br0">&#91;</span>col<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#93;</span> = <span class="br0">&#40;</span><span class="br0">&#40;</span>row+<span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">%</span>6,<span class="br0">&#40;</span>col+<span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">%</span>6<span class="br0">&#41;</span></p>
<p><span class="br0">&#40;</span>rowSum, colSum<span class="br0">&#41;</span> = <span class="br0">&#40;</span><span class="nu0">0</span>,<span class="nu0">0</span><span class="br0">&#41;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> Postcode:<br />
&nbsp; rowSum += PostCodeDict<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; colSum += PostCodeDict<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> &nbsp;</p>
<p>Postcode += PostCodeMatrix<span class="br0">&#91;</span><span class="br0">&#40;</span>rowSum<span class="sy0">%</span>6<span class="br0">&#41;</span>-<span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="br0">&#40;</span>colSum<span class="sy0">%</span>6<span class="br0">&#41;</span>-<span class="nu0">1</span><span class="br0">&#93;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;(%s)&quot;</span> <span class="sy0">%</span> Postcode</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/postcode-barcode-and-python-code/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sniffing some fresh tomatoes</title>
		<link>http://blog.gingerlime.com/sniffing-some-fresh-tomatoes</link>
		<comments>http://blog.gingerlime.com/sniffing-some-fresh-tomatoes#comments</comments>
		<pubDate>Wed, 03 Sep 2008 21:31:23 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/?p=28</guid>
		<description><![CDATA[Perhaps the title is a little misleading, but it&#8217;s an opportunity to combine two of my greatest loves: food and computers. I suppose even this intro is misleading. Oh. Forget it. Lets get down to business. And this time our business is rather short (and sweet). Running tcpdump on my Linksys router (well, Buffalo WHR-54GS [...]]]></description>
			<content:encoded><![CDATA[<p>Perhaps the title is a little misleading, but it&#8217;s an opportunity to combine two of my greatest loves: food and computers. I suppose even this intro is misleading. Oh. Forget it. Lets get down to business. And this time our business is rather short (and sweet).</p>
<p>Running tcpdump on my Linksys router (well, Buffalo WHR-54GS to be precise, but the same famous <a href="http://en.wikipedia.org/wiki/Linksys_WRT54G_series">WRT54G</a> clone that runs open source <a href="http://en.wikipedia.org/wiki/Linksys_WRT54G_series#Third-party_firmware_projects">firmware</a>). </p>
<p><span id="more-28"></span><br />
I&#8217;ve been running <a href="http://www.polarcloud.com/tomato">Tomato</a> firmware for quite a while now (from version 0.7 or something??). What a wonderful firmware. Definitely the very best. Neat. Stylish. Full of all the features one can think of. And then some. A true work of art.</p>
<p>Alas, I wanted to sniff some traffic to analyse using Wireshark (some SIP stuff, I might cover it some other time), and couldn&#8217;t be bothered getting my old heavy dusty hub out just to capture some packets. I was therefore turning to my fresh Tomato, but no such tool is available. </p>
<p>Well, not quite. </p>
<p>A few google searches concluded that I could probably get a pre-compiled binary, place it on a CIFS network share, and run it. So I did.</p>
<p>I download the latest ipkg of tcpdump off <a href="http://ipkg.nslu2-linux.org/feeds/unslung/wl500g/">ipkg.nslu2-linux.org</a>. Renamed the file to .tar.gz, untar&#8217;d it and extracted the binary inside data.tar.gz (/opt/bin/tcpdump).</p>
<p>I used a CIFS windows share feature on tomato. Straight under Administration->CIFS Client and pointed it to the share with the tcpdump binary. Telnet onto the router and off you go, saving the packet dump onto the same windows share. Then analyse it with Wireshark. Job Done. Smells delicious, doesn&#8217;t it?</p>
<div class="codesnip-container" ># telnet 192.168.0.1<br />
Trying 192.168.0.1&#8230;<br />
Connected to 192.168.0.1.<br />
Escape character is &#8216;^]&#8217;.<br />
unknown login: root<br />
Password: </p>
<p>Tomato v1.21.1515</p>
<p>BusyBox v1.2.2 (2008.07.26-14:43+0000) Built-in shell (ash)<br />
Enter &#8216;help&#8217; for a list of built-in commands.</p>
<p># cd /cifs1<br />
# ./tcpdump ip host 192.168.0.110 -w ./dumpfile.txt -s0<br />
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 65535 bytes</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/sniffing-some-fresh-tomatoes/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>JDK 5 Debian etch Virtuozzo installation oddities</title>
		<link>http://blog.gingerlime.com/jdk-installation-oddities</link>
		<comments>http://blog.gingerlime.com/jdk-installation-oddities#comments</comments>
		<pubDate>Thu, 03 Apr 2008 18:42:48 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/jdk-installation-oddities</guid>
		<description><![CDATA[Not a particularly interesting post, unless you happen to be running Debian 4.0 etch running on Virtuozzo host and are trying to install JDK5. I saw a post with a user reporting the same error on the parallels forum , but couldn&#8217;t find a clear solution, until I bumped onto a weird forum in German, [...]]]></description>
			<content:encoded><![CDATA[<p>Not a particularly interesting post, unless you happen to be running Debian 4.0 etch running on Virtuozzo host and are trying to install JDK5. I saw a post with a user reporting the same error on the <a href="http://forum.swsoft.com/showthread.php?t=50509">parallels forum</a> , but couldn&#8217;t find a clear solution, until I bumped onto a weird forum in German, which luckily linked to a related <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=402067">bug report</a> (in English).<br />
<span id="more-26"></span></p>
<p>So if you get this error message when installing jdk5:</p>
<div class="codesnip-container" >Setting up sun-java5-bin (1.5.0-14-1etch1) &#8230;<br />
Could not create the Java virtual machine.<br />
dpkg: error processing sun-java5-bin (&#8211;configure):<br />
 subprocess post-installation script returned error exit status 1<br />
Errors were encountered while processing:<br />
 sun-java5-bin<br />
E: Sub-process /usr/bin/dpkg returned an error code (1)</div>
<p>The solution is to edit the postinst script</p>
<div class="codesnip-container" ># vi /var/lib/dpkg/info/sun-java5-bin.postinst</div>
<p>comment out one line below:</p>
<div class="codesnip-container" ># activate class data sharing<br />
    case i386 in i386|sparc)<br />
        rm -f $basedir/jre/lib/i386/client/classes.jsa<br />
        ### $basedir/bin/java -client -Xshare:dump > /dev/null<br />
    esac</div>
<p>Then reinstall. Ugly, but it seems to do the trick</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/jdk-installation-oddities/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Turbogears, Lighttpd and WSGI for real dummies</title>
		<link>http://blog.gingerlime.com/turbogears-lighttpd-and-wsgi-for-real-dummies</link>
		<comments>http://blog.gingerlime.com/turbogears-lighttpd-and-wsgi-for-real-dummies#comments</comments>
		<pubDate>Fri, 14 Sep 2007 19:49:39 +0000</pubDate>
		<dc:creator>Yoav Aner</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.gingerlime.com/turbogears-lighttpd-and-wsgi-for-real-dummies</guid>
		<description><![CDATA[Just so to set the records straight, I&#8217;m the real dummy here, as you would obviously see. I absolutely have no experience with python, lighttpd, turbogears or wsgi, fcgi but I was given a task to set it up on a server. All I used was some online posts and common sense. Normally I wouldn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>Just so to set the records straight, I&#8217;m the real dummy here, as you would obviously see. </p>
<p>I absolutely have no experience with python, lighttpd, turbogears or wsgi, fcgi but I was given a task to set it up on a server. All I used was some online posts and common sense. Normally I wouldn&#8217;t have to post a blog entry about it, most of the stuff is already out there. On this occasion however, I felt there&#8217;s some missing documentation, or else &#8211; simply because I don&#8217;t know anything about any of these it was more tricky than it usually is. Perhaps it&#8217;s one indicator how this all seems from the sysadmin perspective, as opposed to a turbogears developer.<br />
<span id="more-24"></span><br />
I&#8217;m not going to cover every step, because I feel the basics should be easy enough to follow if you&#8217;ve done some linux server setup. Documentation is pretty clear on the basic install stuff. Nevertheless, some things aren&#8217;t too clear, and I hope to cover at least to some extent. For example, I wasn&#8217;t quite sure whether I should rely on the debian packages or the python easy_setup ones, that can be retrieved automagically. I guess easy_setup is a good bet for the latest versions, as I&#8217;m using Debian 4 stable (etch), and try to avoid mixing stable and unstable, test &#8211; mostly because I&#8217;m not confident enough about not screwing things up</p>
<p>Ok, down to business then<br />
I&#8217;m running: </p>
<ul>Debian stable (Etch)<br />
python 2.4<br />
python setup tools (debian package)<br />
Turbogears 1.0.1 (debian package)<br />
Lighttpd (debian package)<br />
flup and scgi installed via easy_setup</ul>
<p>First thing I wasn&#8217;t sure about, is where to place the turbogears apps. I then decided to create /var/turbogears and put them under there. I don&#8217;t think it makes a huge difference, but seemed sensible enough.</p>
<p>I then created a turbogears app using </p>
<div class="codesnip-container" >
<div class="dos codesnip">/var/turbogears# tg-admin quickstart<br />
Enter project name: newproject<br />
Enter package name <span class="br0">&#91;</span>newproject<span class="br0">&#93;</span>:<br />
<a href="http://www.ss64.com/nt/do.html"><span class="kw1">Do</span></a> you need Identity <span class="br0">&#40;</span>usernames/passwords<span class="br0">&#41;</span> <a href="http://www.ss64.com/nt/in.html"><span class="kw1">in</span></a> this project? <span class="br0">&#91;</span>no<span class="br0">&#93;</span><br />
&#8230;</div>
</div>
<p>so now there&#8217;s a new project called newproject under /var/turbogears/newproject.<br />
<br />
I then tried to follow <a href="http://cleverdevil.org/computing/34/deploying-turbogears-with-lighttpd-and-scgi">this link</a> (or <a href="http://docs.turbogears.org/1.0/LightTPD">this one</a> &#8211; which is essentially a mirror), to have it all served by lighty and wsgi, but then started having problems&#8230; Well &#8211; it simply wouldn&#8217;t work<br />
<br />
I wasn&#8217;t very surprised considering all I did was a copy&#038;paste job, without really understanding what&#8217;s going on. Getting to the root cause was somehow more of a challenge.</p>
<p>I wish I noted all the tiny different things I tried, but I&#8217;ll try to describe a couple of ones that helped along the way:<br />
<br />
enabling more detailed debugging in lighttpd.conf:</p>
<div class="codesnip-container" >debug.log-request-handling = &#8220;enable&#8221;<br />
scgi.debug = 1</div>
<p>Another thing that took me ages to figure out from reading on the links above, what is actually <strong>/full/path/to/your/application</strong> supposed to point at?? I tried /var/turbogears/newproject/newproject-start-scgi.py (which is the new script I created by following the instructions) and /var/turbogears/newproject/ etc.<br />
<br />
the correct answer is <strong>/var/turbogears/newproject/newproject</strong> (i.e. the folder where the application is UNDER the project, they are named the same when using the tg-admin quickstart)</p>
<p>so my lighttpd configuration looks like (after resolving it, I obviously took the debug statements out):</p>
<div class="codesnip-container" >
<div class="apache codesnip">server.document-root = <span class="st0">&quot;/var/turbogears/newproject/newproject&quot;</span><br />
<span class="co1">#debug.log-request-handling = &quot;enable&quot;</span><br />
<span class="co1">#scgi.debug = 1</span></p>
<p>$HTTP[<span class="st0">&quot;url&quot;</span>] !~ <span class="st0">&quot;^/static/&quot;</span> {<br />
&nbsp; scgi.server = (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;/&quot;</span> =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( <span class="st0">&quot;127.0.0.1&quot;</span> =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;host&quot;</span> =&gt; <span class="st0">&quot;127.0.0.1&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;port&quot;</span> =&gt; <span class="nu0">4000</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;check-local&quot;</span> =&gt; <span class="st0">&quot;disable&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br />
}</div>
</div>
<p>
That didn&#8217;t solve the problem unfortunately. I was getting lots of these errors (in /var/log/lighttpd/error.log), even when running the new modified turbogears script (newproject-start-scgi.py):</p>
<div class="codesnip-container" >2007-09-10 16:38:57: (response.c.258) URI-path     :  /<br />
2007-09-10 16:38:57: (mod_scgi.c.2760) handling it in mod_scgi<br />
2007-09-10 16:38:57: (response.c.372) &#8212; before doc_root<br />
2007-09-10 16:38:57: (response.c.373) Doc-Root     : /var/turbogears/newproject/<br />
2007-09-10 16:38:57: (response.c.374) Rel-Path     : /<br />
2007-09-10 16:38:57: (response.c.375) Path         :<br />
2007-09-10 16:38:57: (response.c.423) &#8212; after doc_root<br />
2007-09-10 16:38:57: (response.c.424) Doc-Root     : /var/turbogears/newproject/<br />
2007-09-10 16:38:57: (response.c.425) Rel-Path     : /<br />
2007-09-10 16:38:57: (response.c.426) Path         : /var/turbogears/newproject/<br />
2007-09-10 16:38:57: (response.c.443) &#8212; logical -> physical<br />
2007-09-10 16:38:57: (response.c.444) Doc-Root     : /var/turbogears/newproject/<br />
2007-09-10 16:38:57: (response.c.445) Rel-Path     : /<br />
2007-09-10 16:38:57: (response.c.446) Path         : /var/turbogears/newproject/<br />
2007-09-10 16:38:57: (mod_scgi.c.1325) connect delayed, will continue later: 7<br />
2007-09-10 16:38:57: (mod_scgi.c.2239) got proc: 7 0  4000 1<br />
2007-09-10 16:38:57: (mod_scgi.c.1179) release proc: 7 0<br />
2007-09-10 16:38:57: (mod_scgi.c.2029) proc: 127.0.0.1 4000  1 0 0 0<br />
2007-09-10 16:38:58: (mod_scgi.c.2029) proc: 127.0.0.1 4000  1 0 0 0<br />
2007-09-10 16:38:59: (mod_scgi.c.2029) proc: 127.0.0.1 4000  1 0 0 0</div>
<p>And at some other point (apologies, don&#8217;t remember exactly when was what)</p>
<div class="codesnip-container" >2007-09-10 16:49:48: (response.c.206) URI-path     :  /<br />
2007-09-10 16:49:48: (response.c.207) URI-query    :<br />
2007-09-10 16:49:48: (response.c.257) &#8212; sanatising URI<br />
2007-09-10 16:49:48: (response.c.258) URI-path     :  /<br />
<strong>2007-09-10 16:49:48: (mod_scgi.c.2825) no fcgi-handler found for: /</strong><br />
2007-09-10 16:49:48: (mod_scgi.c.2029) proc: 127.0.0.1 4000  5 0 0 0<br />
2007-09-10 16:49:49: (mod_scgi.c.2029) proc: 127.0.0.1 4000  5 0 0 0</div>
<p>
After very long googling experience, I came across <a href="http://trac.turbogears.org/ticket/193">this link!</a> and then modified my turbogears startup script as it recommended, but with the following modifications where it said <strong>modulename=&#8221;gtextranet.config.app&#8221;</strong> I changed it to <strong>newproject</strong>.config (without the .app), and obviously the line that now says <strong>from newproject.controllers import Root</strong></p>
<div class="codesnip-container" >
<div class="python codesnip"><span class="co1">#!/usr/bin/env python</span><br />
<span class="kw1">import</span> pkg_resources<br />
pkg_resources.<span class="me1">require</span><span class="br0">&#40;</span><span class="st0">&quot;TurboGears&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">import</span> turbogears<br />
<span class="kw1">import</span> cherrypy<br />
cherrypy.<span class="me1">lowercase_api</span> = <span class="kw2">True</span></p>
<p><span class="kw1">from</span> <span class="kw3">os</span>.<span class="me1">path</span> <span class="kw1">import</span> <span class="sy0">*</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span></p>
<p><span class="co1"># first look on the command line for a desired config file,</span><br />
<span class="co1"># if it&#8217;s not on the command line, then</span><br />
<span class="co1"># look for setup.py in this directory. If it&#8217;s not there, this script is</span><br />
<span class="co1"># probably installed</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span> <span class="sy0">&gt;</span> <span class="nu0">1</span>:<br />
&nbsp; &nbsp; turbogears.<span class="me1">update_config</span><span class="br0">&#40;</span>configfile=<span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; modulename=<span class="st0">&quot;newproject.config&quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">elif</span> exists<span class="br0">&#40;</span>join<span class="br0">&#40;</span>dirname<span class="br0">&#40;</span>__file__<span class="br0">&#41;</span>, <span class="st0">&quot;setup.py&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; turbogears.<span class="me1">update_config</span><span class="br0">&#40;</span>configfile=<span class="st0">&quot;dev.cfg&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; modulename=<span class="st0">&quot;newproject.config&quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">else</span>:<br />
&nbsp; &nbsp; turbogears.<span class="me1">update_config</span><span class="br0">&#40;</span>configfile=<span class="st0">&quot;prod.cfg&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; modulename=<span class="st0">&quot;newproject.config&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">from</span> newproject.<span class="me1">controllers</span> <span class="kw1">import</span> Root<br />
<span class="kw1">from</span> cherrypy._cpwsgi <span class="kw1">import</span> wsgiApp<br />
<span class="co1">#from paste.util.scgiserver import serve_application</span><br />
<span class="kw1">from</span> flup.<span class="me1">server</span>.<span class="me1">scgi</span> &nbsp;<span class="kw1">import</span> WSGIServer<br />
<span class="co1">#from flup.server.scgi_fork &nbsp;import WSGIServer</span></p>
<p>port = <span class="nu0">4000</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span> <span class="sy0">&gt;</span> <span class="nu0">2</span>:<br />
&nbsp; &nbsp; port = <span class="kw2">int</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p>cherrypy.<span class="me1">config</span>.<span class="me1">update</span><span class="br0">&#40;</span><span class="br0">&#123;</span><br />
<span class="st0">&#8216;global&#8217;</span>: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;autoreload.on&#8217;</span>: <span class="kw2">False</span>,<br />
<span class="br0">&#125;</span><span class="br0">&#125;</span><span class="br0">&#41;</span><br />
cherrypy.<span class="me1">root</span> = Root<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
cherrypy.<span class="me1">server</span>.<span class="me1">start</span><span class="br0">&#40;</span>initOnly=<span class="kw2">True</span>, serverClass=<span class="kw2">None</span><span class="br0">&#41;</span><br />
<span class="co1">#serve_application(application=wsgiApp, prefix=&#8217;/', port=port)</span><br />
WSGIServer<span class="br0">&#40;</span>application=wsgiApp, bindAddress=<span class="br0">&#40;</span><span class="st0">&#8216;localhost&#8217;</span>, port<span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">run</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
<p></p>
<p>Don&#8217;t ask me what made the difference with this script, as I said before I know nothing about python or turbogears, but it seemed to work.<br />
I had to launch the new script</p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="sy0">/</span>var<span class="sy0">/</span>turbogears<span class="sy0">/</span>newproject <span class="co0">#./newproject-start-scgi.py</span></div>
</div>
<p>last thing I did was to set up a bash script to launch this newproject-start-scgi.py script when the system boots. I used a rather basic bash script placed under /etc/init.d:</p>
<div class="codesnip-container" >
<div class="bash codesnip"><span class="co0">#!/bin/sh</span><br />
<span class="re2">SCRIPT</span>=<span class="st0">&quot;/var/turbogears/newproject/newproject-start-scgi.py&quot;</span><br />
<span class="kw1">case</span> <span class="st0">&quot;$1&quot;</span> <span class="kw1">in</span><br />
start<span class="br0">&#41;</span> &nbsp;<span class="kw3">echo</span> <span class="st0">&quot;STARTING <span class="es2">$SCRIPT</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$SCRIPT</span> <span class="sy0">&amp;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">;;</span><br />
stop<span class="br0">&#41;</span> &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;STOP <span class="es2">$SCRIPT</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re2">pid</span>=<span class="sy0">`/</span>bin<span class="sy0">/</span><span class="kw2">ps</span> <span class="re5">-ef</span> <span class="sy0">|</span> <span class="sy0">/</span>usr<span class="sy0">/</span>bin<span class="sy0">/</span><span class="kw2">awk</span> <span class="st_h">&#8216;($9~&quot;newproject&quot; &amp;&amp; $3==1){printf &quot; &quot;$2}&#8217;</span><span class="sy0">`</span><br />
<span class="co0">##</span><br />
<span class="co0">## please check if this computation of pid is correct on your system</span><br />
<span class="co0">##</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re5">-n</span> <span class="st0">&quot;<span class="es2">$pid</span>&quot;</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">/</span>bin<span class="sy0">/</span><span class="kw2">kill</span> <span class="re1">$pid</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">;;</span><br />
<span class="sy0">*</span><span class="br0">&#41;</span> &nbsp; &nbsp; &nbsp;<span class="kw3">echo</span> <span class="st0">&quot;Usage: $0 {start|stop}&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">exit</span> <span class="nu0">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">;;</span><br />
<span class="kw1">esac</span><br />
<span class="kw3">exit</span> <span class="nu0">0</span></div>
</div>
<p>Even this script is probably crap and shows my lack of refined (or even basic) bash scripting experience, but it seemed to do the trick too</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gingerlime.com/turbogears-lighttpd-and-wsgi-for-real-dummies/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
