<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Code Penguin</title>
	
	<link>http://laurent.bachelier.name</link>
	<description>Musings on software, internet and technology by Laurent Bachelier</description>
	<lastBuildDate>Thu, 16 Jun 2011 20:27:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<feedburner:info uri="laurentb" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://laurent.bachelier.name/feed/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://laurent.bachelier.name/feed/" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsalloy.com/?rss=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.yourminis.com/subscribe.aspx?u=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.yourminis.com/images/addtoyourminisbadge.gif">Subscribe with Yourminis.com</feedburner:feedFlare><feedburner:feedFlare href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://hub.netomat.net/account/account.autoSubscribe.jspa?urls=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.netomat.net/blogger/images/icon_netomat_feedbutton.gif">Subscribe with netomat Hub</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>Achievement</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/srPu50Z5TDQ/</link>
		<comments>http://laurent.bachelier.name/2011/06/achievement/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 20:27:17 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[giddyup]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[seinfeld]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=281</guid>
		<description><![CDATA[While the Seinfeld calendar greatly helped me to get the habit of doing something productive, the service I used has its flaws. First, it&#8217;s restricted to GitHub. Also, since it only counts commits, and not the fact that I can work without any finished product, it made me prefer short work and postpone doing stuff I [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:0f5549b3f417205157e1e6db82704e292bc7750b'><p><a href="http://calendaraboutnothing.com/~laurentb"><img src="http://laurent.bachelier.name/wp-content/uploads/2011/06/seinfeld.png" alt="Seinfeld calendar, 100 days" width="148" height="76" class="alignnone size-full wp-image-282" /></a></p>
<p>While the <a href="http://lifehacker.com/281626/jerry-seinfelds-productivity-secret">Seinfeld calendar</a> greatly helped me to get the habit of doing something productive, the <a href="http://calendaraboutnothing.com/">service</a> I used has its flaws. First, it&#8217;s restricted to GitHub. Also, since it only counts commits, and not the fact that I can work without any finished product, it made me prefer short work and postpone doing stuff I wasn&#8217;t sure I would finish before 00:00 (the fact I start late does not help either). The notion of a day is also wrong — committing at 00:30 should not be counted for the current day but the previous one.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/srPu50Z5TDQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/06/achievement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/06/achievement/</feedburner:origLink></item>
		<item>
		<title>Some clarifications on symfttpd</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/9kd1hRAzUDg/</link>
		<comments>http://laurent.bachelier.name/2011/03/some-clarifications-on-symfttpd/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 18:24:15 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=267</guid>
		<description><![CDATA[The basic idea is to start a server without any central configuration to maintain, and no need for any root access, hence generic virtual hosts features of Apache or lighttpd are not complete alternatives, as they at least require editing /etc/hosts. It uses the FastCGI backend (or &#8220;SAPI&#8221;) and can by default handle 3 concurrent [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:30364a44b1994a1c50b606c2b8fdf1711e44bc58'><p>The basic idea is to start a server without any central configuration to maintain, and no need for any root access, hence generic virtual hosts features of Apache or lighttpd are not complete alternatives, as they at least require editing <code>/etc/hosts</code>.</p>
<p>It uses the FastCGI backend (or &#8220;SAPI&#8221;) and can by default handle 3 concurrent requests, which is more than enough for development. On the production side, I only use symfttpd to generate the rewrite rules (since lighttpd is also my production server of choice). If you have an opcode cache installed (for instance APC or xcache), it will be used, as fastcgi processes are seldom restarted (by default every 100 requests, I use a higher number on production though). It also does not rely on any hacks to simulate a web request in the CLI: you are doing real requests using a real PHP HTTP backend.</p>
<p>One of the future improvements could be using <a href="http://php.net/manual/en/install.fpm.php">FPM</a> instead of FastCGI.</p>
<p><a href="https://github.com/laurentb/symfttpd">Symfttpd</a> can optionality use the <code><a href="http://php.net/manual/en/function.pcntl-fork.php">fork</a></code> function to provide two nice features: automatically restart when rewriting rules change, and display the access and error log. However, if you do not have fork support compiled in (it is enabled by default in at least Gentoo, Debian and Ubuntu), it does not mean only one request can be answered at a time (<a href="http://www.lighttpd.net/">lighttpd</a> does not need <code>fork()</code> by the way, which is one of the reasons it is very fast).</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/9kd1hRAzUDg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/03/some-clarifications-on-symfttpd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/03/some-clarifications-on-symfttpd/</feedburner:origLink></item>
		<item>
		<title>The sad quest for a portable audiophile setup</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/ancrtgSWM10/</link>
		<comments>http://laurent.bachelier.name/2011/03/the-sad-quest-for-a-portable-audiophile-setup/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 22:37:12 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[standards]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=251</guid>
		<description><![CDATA[I don&#8217;t like to listen to stuff loud. People usually listen loud because their setups are bad and it compensates somewhat. Well, I&#8217;d like to preserve my hearing — already imperfect — as much as possible. With my current IEMs, the outside noise is actually louder than when I wear them and play music. In [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:1234b822e110050c24bf9c6fcc0f21c30158ac77'><p>I don&#8217;t like to listen to stuff loud. People usually listen loud because their setups are bad and it compensates somewhat. Well, I&#8217;d like to preserve my hearing — already imperfect — as much as possible. With my current <a href="http://en.wikipedia.org/wiki/In-ear_monitor">IEMs</a>, the outside noise is actually louder than when I wear them and play music. In a way, it&#8217;s even better for my hearing!</p>
<p>The issue is that nowadays, pretty much all portable players are crap. They rarely support interesting formats. Their amplifier stages are tuned for loudness and sacrifice the <a href="http://en.wikipedia.org/wiki/Loudness_war">dynamic range</a>. Their interfaces are animated and shiny, yet don&#8217;t get shit done.</p>
<p>The most popular remedy to bad amplifiers is to use an Apple device, as the proprietary connector provides line out, which is an unamplified signal, and to use an external amplifier. Some other devices provide line out, but are much harder to find. The recommended choice is an iPod 5.5th generation or below, as their <a href="http://en.wikipedia.org/wiki/Digital-to-analog_converter">DACs</a> are of reasonable quality, but mostly because they are not as locked down as the new ones.</p>
<p>Hopefully, you can replace Apple&#8217;s horrible software by <a href="http://www.rockbox.org/">Rockbox</a>, an open source alternative that will allow you to get rid of the iTunes dependency or support open and high-quality formats such as FLAC and Ogg Vorbis. One of the perks I get with it is the speaking menus — you can more or less control the device without looking at it, which is not easy to do when there are no buttons but only the ergonomic absurdity that is the &#8220;clickwheel&#8221;. It can also announce the battery status. The ReplayGain feature prevents me from having to adjust the volume between albums.</p>
<p>Another issue with iPods is the usage of an hard drive. While cheaper than Flash memory, it is much more unreliable and requires more power. You can however <a href="http://www.tarkan.info/20080126/tutorials/32gb-compact-flash-ipod">replace the hard drive by a CompactFlash card</a>.</p>
<p>My current setup consists of an iPod 5.5g 30gb, with the hard drive replaced by a 32 GB flash drive (it wasn&#8217;t much of a choice, given the horrible noise the drive was making). It uses a SendStation Line Out and Micro USB adapter (no need to use a proprietary cable!), which is then hooked to an <a href="http://www.ibasso.com/en/products/show.asp?ID=37">iBasso T4 amplifier</a>. The amplifier provides me with an hardware volume potentiometer which for that reason alone is worth it. The final stage is handled by the <a href="http://anythingbutipod.com/2007/06/future-sonics-atrio-m5-m8-review/">Future Sonics Atrio M5</a>.</p>
<p><a href="http://laurent.bachelier.name/wp-content/uploads/2011/03/dap.jpg"><img src="http://laurent.bachelier.name/wp-content/uploads/2011/03/dap-300x216.jpg" alt="" title="My setup" width="300" height="216" class="aligncenter size-medium wp-image-253" /></a></p>
<p>Am I happy with it? Well, the sound quality is more than enough. I doubt I could enjoy my music more by upgrading to something else. However, I have a lot of unrelated complaints:</p>
<p>I spent 80€ on the iPod yet much more to make it suck less. And it still sucks. The build quality is shoddy, I frequently have to open it to reconnect components. It powers itself on even when the &#8220;lock&#8221; switch is activated, draining the battery needlessly. The clickwheel is a pain to use and I can sense it dying. The screen is shiny and obviously unreadable under the sun. Dust is getting inside. It is very slow to power on. The battery isn&#8217;t in a good shape, but the Flash memory and usage of an external amplifier compensate for now.</p>
<p>iTunes wasn&#8217;t able to restore the iPod properly when I changed the drive, so I had to mirror the drive exactly to the CompactFlash card (losing the additional 2 GB of space), contrarily to what was stated on the adapter&#8217;s website. Since I&#8217;m probably not the only one with the same issue out there, here is a <a href="http://stuff.laurent.bachelier.name/raw_ipod.img.xz">raw copy</a> of the drive with Rockbox installed as the only OS. It also was a bitch to open, even for an Apple product.</p>
<p>Uploading files to the iPod is slow as hell, and sometimes fails. It seems it doesn&#8217;t like writing more than a few gigabytes in a row. And the dock adapter has a tendency to come out.</p>
<p>To sum up, I&#8217;m using an iPod but discarding its software, and half its hardware.</p>
<p>The iBasso T4 uses a proprietary cable to recharge. Other than that, it caught many shocks but still works flawlessly. And it can be opened with a screwdriver.</p>
<p>As for the Atrio, for 100€, they were a solid choice. Now that they cost twice as much (and still are the same product) there probably are better options. I use Comply T100 foam tips, and they are generally compatible with Shure eartips (which motivated my choice since I have a bunch of them in stock). One nice touch is that the user&#8217;s manual recommends against any artificial bass enhancements: you know you&#8217;re not dealing with crappy phones.</p>
<p>So, what would I recommend instead? Well, I&#8217;d probably get a FiiO E7 or another iBasso model. But for the media player, I&#8217;m stuck. Hence the title.</p>
<p>There might be some hope on the side of the <a href="http://en.wikipedia.org/wiki/PDMI">PDMI connector</a>, though.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/ancrtgSWM10" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/03/the-sad-quest-for-a-portable-audiophile-setup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/03/the-sad-quest-for-a-portable-audiophile-setup/</feedburner:origLink></item>
		<item>
		<title>symfttpd 1.1.1 released</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/J1NfYuQ0-cY/</link>
		<comments>http://laurent.bachelier.name/2011/02/symfttpd-1-1-1-released/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 23:00:57 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[lighttpd]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=242</guid>
		<description><![CDATA[You can now use genconf without linking or copying it inside the project. It also makes the usage of mksymlinks more or less optional if you just want to use spawn. Not much else too see apart from small bug fixes and documentation improvements. Download symfttpd 1.1.1. More information on GitHub. There is also a [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:b73559fc46954f736eb03798d60f5a76cdd438bf'><p>You can now use <code>genconf</code> without linking or copying it inside the project. It also makes the usage of <code>mksymlinks</code> more or less optional if you just want to use <code>spawn</code>.</p>
<p>Not much else too see apart from small bug fixes and documentation improvements.</p>
<p>Download <a href="https://github.com/downloads/laurentb/symfttpd/symfttpd-1.1.1.tar.bz2">symfttpd 1.1.1</a>.<br />
More information on <a href="https://github.com/laurentb/symfttpd">GitHub</a>.</p>
<p>There is also a <a href="https://github.com/fabriceb/symfttpd/tree/symfony2">adaptation</a> of the current code for usage with Symfony2. However, it removes support of 1.x versions; a multiple-application update of symfttpd is coming soon.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/J1NfYuQ0-cY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/02/symfttpd-1-1-1-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/02/symfttpd-1-1-1-released/</feedburner:origLink></item>
		<item>
		<title>symfttpd 1.1.0 released</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/L6HdAnsR3_Q/</link>
		<comments>http://laurent.bachelier.name/2011/02/symfttpd-1-1-0-released/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 23:48:33 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[lighttpd]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=237</guid>
		<description><![CDATA[This version brings one huge usability change: you don&#8217;t have to restart spawn anymore when a file is added in the web/ directory root. Enjoy being truly lazy! Along with some miscellaneous enhancements, the output of the tools is now colored, and you can display lighttpd&#8217;s logs in the terminal with the -t option. As [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:903e6777568523d183d477167ea1070e07bd0301'><p>This version brings one huge usability change: you don&#8217;t have to restart <code>spawn</code> anymore when a file is added in the <code>web/</code> directory root. Enjoy being truly lazy!</p>
<p>Along with some miscellaneous enhancements, the output of the tools is now colored, and you can display lighttpd&#8217;s logs in the terminal with the <code>-t</code> option.</p>
<p>As always, suggestions and contributions are welcome.</p>
<p>Download <a href="https://github.com/downloads/laurentb/symfttpd/symfttpd-1.1.0.tar.bz2">symfttpd 1.1.0</a>.<br />
More information on <a href="https://github.com/laurentb/symfttpd">GitHub</a>.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/L6HdAnsR3_Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/02/symfttpd-1-1-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/02/symfttpd-1-1-0-released/</feedburner:origLink></item>
		<item>
		<title>More of me</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/m90OkMSZU64/</link>
		<comments>http://laurent.bachelier.name/2011/01/more-of-me/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 20:45:25 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Meta]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=232</guid>
		<description><![CDATA[If the activity of my blog leaves you frustrated and demanding for more, rejoice! I am also writing on my employer&#8217;s blog.]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:16d93eb7337c2e8fe32eac0bbb05e05d9eac6686'><p>If the activity of my blog leaves you frustrated and demanding for more, rejoice! I am also writing on my <a href="http://www.theodo.fr/blog/">employer&#8217;s blog</a>.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/m90OkMSZU64" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/01/more-of-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/01/more-of-me/</feedburner:origLink></item>
		<item>
		<title>A positive note</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/lfJkVOfgcSo/</link>
		<comments>http://laurent.bachelier.name/2011/01/a-positive-note/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 20:20:13 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[symfttpd]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=230</guid>
		<description><![CDATA[I have grown very fond of Symfony 1.4. It&#8217;s pretty much Symfony 1.2 with all the quicks ironed out. It showed me how much polish is important in a software project. It&#8217;s almost all I have been doing in my own little project after the main features were implemented, symfttpd: making it less annoying to [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:bb66278d89610a1c6688cd7e7074f081b41e94a1'><p>I have grown very fond of Symfony 1.4. It&#8217;s pretty much Symfony 1.2 with all the quicks ironed out. It showed me how much <em>polish</em> is important in a software project.</p>
<p>It&#8217;s almost all I have been doing in my own little project after the main features were implemented, <a href="https://github.com/laurentb/symfttpd">symfttpd</a>: making it less annoying to use, less unpredictable, etc. And I must say, the current stable version has at least one very annoying quirk (but if it&#8217;s documented, does it count as a feature?).</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/lfJkVOfgcSo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2011/01/a-positive-note/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2011/01/a-positive-note/</feedburner:origLink></item>
		<item>
		<title>Don’t forget the other kind of WTF</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/J3Eab2kXlJM/</link>
		<comments>http://laurent.bachelier.name/2010/08/dont-forget-the-other-kind-of-wtf/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 23:53:14 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[wtf]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=195</guid>
		<description><![CDATA[Sometimes, the code looks good, but it doesn&#8217;t mean that the whole project in itself is good. First, a project should be simple to install. The install documentation should exist and always be up to date. I encounter too many projects where &#8220;inside knowledge&#8221; is required to install the application, and you don&#8217;t know if [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:c04175613e3e20ff4a07ac0cf840ab340e34af5c'><p>Sometimes, the code looks good, but it doesn&#8217;t mean that the whole project in itself is good.</p>
<p>First, a project should be simple to install. The install documentation should exist and always be up to date. I encounter too many projects where &#8220;inside knowledge&#8221; is required to install the application, and you don&#8217;t know if it doesn&#8217;t work because you didn&#8217;t install it right or it just doesn&#8217;t work. There should be a single command (makefiles or shell scripts are here for that) for a single task. It should not require weird system settings (this is very annoying with PHP when a lot of the language is customizable through <code>php.ini</code>).</p>
<p>On a similar note, the architecture should be simple to comprehend. When it feels too much like &#8220;magic&#8221;, when a simple action has too many unsaid consequences, something is wrong. There should not be hundreds of classes and inheritances when an option would be enough (this is an idea found at least in Python and Symfony 1.4 that I quite like). Names should be readable and short, not everyone has or likes using auto-completion.</p>
<p>I&#8217;m not sure what creates this kind of WTF. Inexperienced but talented programmers? Programmers who think too high of themselves? Programmers that are <em>not</em><em> lazy enough?</em></p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/J3Eab2kXlJM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/08/dont-forget-the-other-kind-of-wtf/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/08/dont-forget-the-other-kind-of-wtf/</feedburner:origLink></item>
		<item>
		<title>chmod 777 is evil</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/gUeiSnLJmbk/</link>
		<comments>http://laurent.bachelier.name/2010/07/chmod-777-is-evil/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 08:07:20 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=131</guid>
		<description><![CDATA[Well, chmod 666 is the true evil obviously, but people who use the chmod 777 trick really don&#8217;t want to bother with the different signification of x for files and folders, so they mark all files as executables. This makes ls in my terminal quite ugly, and is what motivated me to write yet another [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:5a49026651bd08aa4e816c1360225ee63973fc01'><p>Well, chmod 666 is the true evil obviously, but people who use the <em>chmod 777 trick</em> really don&#8217;t want to bother with the different signification of <code>x</code> for files and folders, so they mark all files as executables. This makes <code>ls</code> in my terminal quite ugly, and is what motivated me to write yet another rant!</p>
<p>Traditionally, the web server runs with a special, underprivileged user. Now, this is totally fine — I&#8217;ll get back to that later. However, when a developer starts a project, he naturally does it with his own account. This is fine, too. When he wants to test it, he installs a web server (let&#8217;s say Apache and mod_php<sup><a href="http://laurent.bachelier.name/2010/07/chmod-777-is-evil/#footnote_0_131" id="identifier_0_131" class="footnote-link footnote-identifier-link" title="I don&#039;t like much both of them, but more on that later">1</a></sup>), and tells the web server to use the project directory. However, the web server&#8217;s user can&#8217;t read, or at least can&#8217;t write in the directory. And here, our web developers asking for help gets recommended to &#8220;chmod 777&#8243;. Symfony even has a command for doing it, and it is a real shame.</p>
<p>It will work. It will also make an ugly git commit, and an ugly <code>ls</code>. Il will create files owned by the web server, and the developer is likely to use <code>sudo</code> before every command to work around the problems that will ensue, and it just gets insane.</p>
<p>Separation of privileges is what makes UNIX systems great. Let&#8217;s understand them and use them, please.</p>
<p>The obvious solution here is to run your development server under the development user. There is no need to separate when it&#8217;s for your own usage. There is a even better solution, embraced by almost every language but PHP: a way to start a web server on demand. I believe it was started by Ruby on Rails with WEBrick, and now every non-PHP framework has it. Python, by using <a href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface">WSGI</a> makes it very easy. I simulated this feature for Symfony by writing <a href="http://laurent.bachelier.name/2010/05/reducing-the-gap-between-symfony-and-non-php-frameworks/">symfttpd</a>. It&#8217;s actually simpler for the developer as there is no configuration or installation at all.</p>
<p>Enough about developers; it&#8217;s not their job to setup daemons and manage UNIX systems. Let&#8217;s talk about the real accomplices of the Devil: system administrators.</p>
<p>Yes, there are system administrators that don&#8217;t use permissions properly. And they are legion. I&#8217;ve seen horrors, up to &#8220;sudo svn up&#8221; on the production server, because half the files ended being owned by root. And then &#8220;chmod 777&#8243; on millions of files.</p>
<p>There are many solutions there; group inheritance with the <a href="http://en.wikipedia.org/wiki/Setuid#setuid_and_setgid_on_directories">setgid bit</a>, forcing the users to <code>su</code> as the web server user, or a deployment script (I&#8217;ve used the three of them for different situations).</p>
<p>Why is this important? Because it is often useful to separate users (one should not have access to the other&#8217;s projects in reading or writing), or to separate projects for security (one hacked project should not give access to the others).</p>
<p>I&#8217;ve seen it… done wrong:</p>
<ul>
<li>safe_mode for PHP. It doesn&#8217;t work and will disappear in newer versions anyway.</li>
<li>Only allowing FTP access to users, who can still upload a PHP script which will have access to everything (if run through the web server). Oh, and FTP sucks. Same issue with SSH and chroot.</li>
<li>Add the users to the <em>group</em> the web server is running as. Allows SSH access. Nice, but the PHP script trick will, again, defeat it.</li>
</ul>
<p>There is only one solution: use the &#8220;group&#8221; solution, but run a different PHP instance for each user. It is quite rarely used because the convenience of <em>Apache</em> and <em>mod_php</em>. But running PHP in the same <em>process</em> as the web server feels quite dangerous for me too. I think <em>mod_php</em> is an abomination.</p>
<p>I&#8217;ve done it for years with <em>Lighttpd</em>, <em>PHP</em> and <em>FastCGI</em> with a few alterations to Gentoo&#8217;s <code>spawn-fgci</code> init script (which is now able to handle multiple configurations without any alteration since a few months). My setup is very similar to <a href="http://redmine.lighttpd.net/wiki/lighttpd/HowToSetupFastCgiIndividualPermissions">that one</a>.</p>
<p>Note that while I mention PHP, this issue is not strictly related to PHP, yet seems widespread in PHP communities.</p>
<ol class="footnotes">
<li id="footnote_0_131" class="footnote">I don&#8217;t like much both of them, but more on that later</li>
</ol>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/gUeiSnLJmbk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/07/chmod-777-is-evil/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/07/chmod-777-is-evil/</feedburner:origLink></item>
		<item>
		<title>Exceptions</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/GGVbyvp9dX8/</link>
		<comments>http://laurent.bachelier.name/2010/07/exceptions/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 23:25:09 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=188</guid>
		<description><![CDATA[I see on a lot of projects stuff like this: function getStuff&#40;&#41; &#123; try &#123; return $this-&#62;retrieveStuff&#40;&#41; &#125; catch &#40;Exception $e&#41; &#123; return null; &#125; &#125; The issue, in this example, is not that we silence an error. It should be logged, but there could be a legitimate use for this. For instance, it requires [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:b93f51103415308f0ee5d5980768d593c9c4267f'><p>I see on a lot of projects stuff like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> getStuff<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  try
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">retrieveStuff</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#125;</span>
  catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The issue, in this example, is not that we silence an error. It should be logged, but there could be a legitimate use for this. For instance, it requires a connection to a remote server we have no control over, and we still want to serve the rest of the content to the user, as the information is not vital.</p>
<p>No, my issue it that we catch all errors, when the aim was to catch only one error (for instance &#8220;unable to connect to that remote server&#8221;). Imagine now there is a real bug in <code>retrieveStuff()</code>, it would still be interpreted by developers as a connection errors.</p>
<p>The solution is to have one exception type per error type (it sounds obvious said that way, doesn&#8217;t it?), and only catch the specific error, for instance <code>ConnectionError</code>.</p>
<p><!-- more --></p>
<p>PHP&#8217;s error handling is historically bad, and even though new features use exceptions, the legacy ones don&#8217;t. Or sometimes functions should trigger a fatal error but it is only a warning, and the code continues, which can trigger unwanted and hard-to-debug results. There are amazing plugins for Symfony that convert errors to exceptions (and warnings seem to be handled properly, i.e. they are logged and don&#8217;t cause the page to fail). It&#8217;s a start.</p>
<p>However, even when you get exceptions, you can&#8217;t always filter them easily. For instance, in Symfony, there are many different errors that would throw the same class. Symfony has a handful of exceptions, Doctrine has a bit more (though they can be quite meaningless!). Overall, there are defined &#8220;by module&#8221; than &#8220;by error&#8221;.</p>
<p>Comparatively, <a href="http://docs.python.org/tutorial/errors.html">Python&#8217;s handling of exceptions</a> is exceptional<sup><a href="http://laurent.bachelier.name/2010/07/exceptions/#footnote_0_188" id="identifier_0_188" class="footnote-link footnote-identifier-link" title="sorry">1</a></sup>. There are exceptions for everything, and most of the time errors are handled by only checking the class and not the contents of the exception. It is probably the feature I love the most about Python. With the <code>else</code>, <code>finally</code>, and <code>with</code> statements, it is almost a pleasure to handle errors.</p>
<ol class="footnotes">
<li id="footnote_0_188" class="footnote">sorry</li>
</ol>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/GGVbyvp9dX8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/07/exceptions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/07/exceptions/</feedburner:origLink></item>
	</channel>
</rss>

