<?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>Tue, 16 Mar 2010 12:53: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>On Twitter</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/qT961KMRoV4/</link>
		<comments>http://laurent.bachelier.name/2010/03/on-twitter/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 12:53:17 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=164</guid>
		<description><![CDATA[Joel Spolsky on Twitter:
Although I appreciate that many people find Twitter to be valuable, I find it a truly awful way to exchange thoughts and ideas. It creates a mentally stunted world in which the most complicated thought you can think is one sentence long. It’s a cacophony of people shouting their thoughts into the [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:f647dd089675c234b8571d4e2d4d8a23077e26d3'><p><a href="http://www.joelonsoftware.com/items/2010/03/14.html">Joel Spolsky on Twitter</a>:</p>
<blockquote><p>Although I appreciate that many people find Twitter to be valuable, I find it a truly awful way to exchange thoughts and ideas. It creates a mentally stunted world in which the most complicated thought you can think is one sentence long. It’s a cacophony of people shouting their thoughts into the abyss without listening to what anyone else is saying. Logging on gives you a page full of little hand grenades: impossible-to-understand, context-free sentences that take five minutes of research to unravel and which then turn out to be stupid, irrelevant, or pertaining to the television series <em>Battlestar Galactica</em>. I would write an essay describing why Twitter gives me a headache and makes me fear for the future of humanity, but it doesn’t deserve more than 140 characters of explanation, and I’ve already spent 820.</p></blockquote>
<p>I couldn't agree more.</p>
<p>I will also be far from being the first to say it, but Twitter is just a poor reimplementation of IRC over HTTP, which is completely inappropriate. Twitter is a constant failure with bad uptime, scalability issues and over-centralization. Twitter is one of the worst things that happened to the Web; it also promotes URL shorteners, which have security issues and double the possible unavailabilities.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/qT961KMRoV4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/03/on-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/03/on-twitter/</feedburner:origLink></item>
		<item>
		<title>Random fail</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/SUevUCxDaVo/</link>
		<comments>http://laurent.bachelier.name/2010/02/random-fail/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 19:05:36 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[random numbers]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=161</guid>
		<description><![CDATA[Yet another case of trying to be too clever with randomness!
]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:7d05d0813bdb1e98aa4d07f5bea11e41155eceab'><p>Yet <a href="http://www.robweir.com/blog/2010/02/microsoft-random-browser-ballot.html">another case</a> of trying to be too clever with randomness!</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/SUevUCxDaVo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/02/random-fail/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/02/random-fail/</feedburner:origLink></item>
		<item>
		<title>Security is not easy</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/ie5B3JdowUQ/</link>
		<comments>http://laurent.bachelier.name/2010/02/security-is-not-easy/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 17:45:54 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[full disclosure]]></category>
		<category><![CDATA[random numbers]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=143</guid>
		<description><![CDATA[Security is not easy. Programmers should leave things like random number and identifier generation to a library (or at least research the best way to do it). A lot of projects learned it the hard way.
Let's talk for instance of a function I encountered about six months ago:
function generateRandomKey&#40;$len = 20&#41;
&#123;
  $string = '';
 [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:2a1fd3c9cf4af19e229610717ad2f7c770de82be'><p>Security is not easy. Programmers should leave things like random number and identifier generation to a library (or at least research the best way to do it). A lot of projects learned it the hard way.</p>
<p>Let's talk for instance of a function I encountered about six months ago:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">function</span> generateRandomKey<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$len</span> = <span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #0000ff;">$string</span> = <span style="color: #ff0000;">''</span>;
  <span style="color: #0000ff;">$pool</span>   = <span style="color: #ff0000;">'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'</span>;
  <span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span> = <span style="color: #cc66cc;">1</span>; <span style="color: #0000ff;">$i</span> &lt; = <span style="color: #0000ff;">$len</span>; <span style="color: #0000ff;">$i</span>++<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$string</span> .= <a href="http://www.php.net/substr"><span style="color: #000066;">substr</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$pool</span>, <a href="http://www.php.net/rand"><span style="color: #000066;">rand</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">61</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <a href="http://www.php.net/md5"><span style="color: #000066;">md5</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$string</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>It is a real gem as it seems it was meant to concentrate everything a programmer should <em>not</em> do.</p>
<p><strong>Flaw 1: </strong> Using <code>rand()</code> instead of <code><a href="http://fr.php.net/manual/en/function.mt-rand.php">mt_rand()</a></code>. Any PHP programmer should know this.</p>
<p><strong>Flaw 2: </strong> Using <code><a href="http://en.wikipedia.org/wiki/MD5#Collision_vulnerability">md5</a>()</code> instead of <code>sha1()</code>. Any PHP programmer should know this too.</p>
<p><strong>Flaw 3: </strong> Generating a 20 character random string and then hashing it to a 32 character string looks a bit silly. Granted, the hash has less different characters, but still the input can have 7.04423e+35 different values while the output can have 3.40282e+38.</p>
<p><strong>Flaw 4: </strong> Calling rand() multiple times. It denotes a strong ignorance on how <a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator">pseudo-random number generators</a> work. Since the seed doesn't change, it can be easy to guess what will be the next number from the previous ones. It isn't "more random" to call it multiple times.</p>
<p><strong>Flaw 5: </strong> Using a very limited range for picking a random number. Also, why choose alphanumeric characters if you are not using them afterwards since they are passed to a hash function? This seems to be very badly designed.</p>
<p><strong>Flaw 6: </strong> Feeding md5 with alphanumeric characters, present in all the <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow tables</a> in the world.</p>
<p><strong>Flaw 7: </strong> Ever heard of <code>chr()</code>?</p>
<p><strong>Flaw 8: </strong> Why reinvent the wheel? At least if you have a reason, leave a comment (no comments at all on this function).</p>
<p>Without even testing if the results are good or not, any programmer should know this function should be completely rewritten.</p>
<p>Let's see how it should have been done.</p>
</pre>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> generateRandomKey<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <a href="http://www.php.net/base_convert"><span style="color: #000066;">base_convert</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/sha1"><span style="color: #000066;">sha1</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/uniqid"><span style="color: #000066;">uniqid</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/mt_rand"><span style="color: #000066;">mt_rand</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #cc66cc;">16</span>, <span style="color: #cc66cc;">36</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p><strong>How did I come up with this?</strong> Mostly be reading the PHP manual and not creating a random number generator, but merely using one.</p>
<p>The use of <code>base_convert()</code> is not really important, it is mostly because the database field was too short (nothing is lost from the <code>sha1()</code>). We actually would be better off without <code>sha1()</code> though, it is there mostly for the eye-candy.</p>
<p><code>uniqid()</code> will take the result of <code>mt_rand()</code> and append it an unique value (but in a predictable range, hence the use of both functions). This is recommended by the PHP manual and is more than enough.</p>
<p>Now you're probably asking yourself where did I find this piece of code.</p>
<p>It is in <a href="http://www.symfony-project.org/plugins/sfGuardPlugin">sfGuardPlugin</a> and <a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin">sfDoctrineGuardPlugin</a>, for the <a href="http://www.symfony-project.org/about"><strong>symfony</strong></a> framework. It's here almost from the <a href="http://trac.symfony-project.org/changeset/2343">start</a>, though it was <a href="http://trac.symfony-project.org/changeset/4644">even</a> <a href="http://trac.symfony-project.org/changeset/4713">wronger</a>. Those are by far the most used plugins, and are endorsed by the official documentation.</p>
<p><strong>What does this mean?</strong> On some systems, it will be very easy to brute-force the cookie to log in as any user. Or an user could accidentally become logged as another one, since collisions are highly likely.</p>
<p><em>Come on, if this is real, someone would have spotted it! I is probably not exploitable.</em><br />
Actually, it is. I have been able to reproduce it on an older Debian server, and on this server was a website where users reported multiple times getting identified as another user (hopefully this server is retired and the project now runs on the fixed function).<br />
I also tried to reproduce it on a Windows XP virtual machine (since it was the easiest way to get a PHP with a flawed random number generator) with <a href="http://laurent.bachelier.name/wp-content/uploads/2010/02/2010-02-05-102444_1280x1024_scrot.png">success</a>. Since on these two machines I got a <em>lot</em> of collisions, even on better systems the flaw should be exploitable with some effort.</p>
<p><strong>Why am I doing this?</strong><br />
Because I <a href="http://trac.symfony-project.org/ticket/7018">reported</a> it six month ago, and it received very little attention.<br />
I think symfony is great, but the handling of security isn't (though my other <a href="http://groups.google.com/group/symfony-devs/msg/1811c52925367bdb">criticisms</a> are more on standard programming or hosting practices encouraged by symfony than on the code; more on the latter in a coming article, be sure to <a href="http://laurent.bachelier.name/feed/">subscribe</a>).</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/ie5B3JdowUQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/02/security-is-not-easy/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/02/security-is-not-easy/</feedburner:origLink></item>
		<item>
		<title>Extract from Doctrine_Record</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/vUxsh2p_8Zc/</link>
		<comments>http://laurent.bachelier.name/2009/07/extract-from-doctrine-record/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 10:58:06 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[funny]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=126</guid>
		<description><![CDATA[&#160;
    /**
     * returns an array of modified fields and associated values
     * @return array
     * @todo What about a better name? getModifiedFields?
     */
    public function getModified&#40;&#41;
    &#123;
   [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:89e51025eaf4ef6f23a16a49c3fcd28dd1a2c234'><pre class="php">&nbsp;
    <span style="color: #808080; font-style: italic;">/**
     * returns an array of modified fields and associated values
     * @return array
     * @todo What about a better name? getModifiedFields?
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getModified<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #0000ff;">$a</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
        <span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;_modified <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$k</span> =&gt; <span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0000ff;">$a</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$this</span>-&gt;_data<span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span>;
        <span style="color: #66cc66;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$a</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/**
     * REDUNDANT?
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> modifiedFields<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #0000ff;">$a</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
        <span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;_modified <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$k</span> =&gt; <span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0000ff;">$a</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$this</span>-&gt;_data<span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span>;
        <span style="color: #66cc66;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$a</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/vUxsh2p_8Zc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/07/extract-from-doctrine-record/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/07/extract-from-doctrine-record/</feedburner:origLink></item>
		<item>
		<title>Extending plugins in PHP and Symfony</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/b7eLjc1-oGo/</link>
		<comments>http://laurent.bachelier.name/2009/06/extending-plugins-in-php-and-symfony/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 09:44:04 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[autoloading]]></category>
		<category><![CDATA[inheritance]]></category>
		<category><![CDATA[monkeypatching]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=71</guid>
		<description><![CDATA[Plugins are great but they are never what you exactly wanted. When they are designed properly, the best way to customize them is to extend them instead of directly editing them.
Now, imagine I have:1
# Penguin.class.php
class Penguin
&#123;
  public function __construct&#40;&#41;
  &#123;
    echo &#34;Windows is bad\n&#34;;
  &#125;
&#125;
&#160;
# Herd.class.php
class Herd
&#123;
  public [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:d53a333a45829cc1cb9275db7c814838c92a15a8'><p>Plugins are great but they are never what you exactly wanted. When they are designed properly, the best way to customize them is to <em>extend</em> them instead of directly editing them.</p>
<p>Now, imagine I have:<sup>1</sup></p>
<pre class="php"><span style="color: #808080; font-style: italic;"># Penguin.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> Penguin
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Windows is bad<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<pre class="php"><span style="color: #808080; font-style: italic;"># Herd.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> Herd
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span>++ &lt; <span style="color: #cc66cc;">42</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">new</span> Penguin<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># test</span>
<span style="color: #000000; font-weight: bold;">new</span> Herd<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre>
<p>I want to change <code>Penguin</code>'s behavior to something a bit more positive. However I don't want to extend <code>Herd</code> especially if it's tied to <code>Penguin</code> everywhere... I'm stuck with the <code>Penguin</code> class and can't use another one.</p>
<p>With some languages you can alter classes dynamically, and it can be referred as <a href="http://parand.com/say/index.php/2006/07/17/ruby-style-adding-methods-to-existing-classes-in-python/">monkeypatching</a>. While it is actually possible in PHP, it is ugly at best; you end up typing code in character strings, losing proper syntax highlighting and the opcode caching. Unless there is a very good language support for these methods it's best to avoid them.</p>
<p>A handful of plugins for Symfony, like <a href="http://www.symfony-project.org/plugins/sfGuardPlugin">sfGuardPlugin</a> (one of the most popular plugins) already have some kind of solution. They come with two classes, a dummy one and a real one:</p>
</pre>
<pre class="php"><span style="color: #808080; font-style: italic;"># Penguin.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> Penguin <span style="color: #000000; font-weight: bold;">extends</span> pluginPenguin
<span style="color: #66cc66;">&#123;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<pre class="php"><span style="color: #808080; font-style: italic;"># pluginPenguin.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> pluginPenguin
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Windows is bad<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p>Which means you just have to edit the (almost) blank <code>Penguin</code> class.<br />
This is a clean, object-oriented way to solve the problem.</p>
<p>However, there are practicals problems that will arise.</p>
<ul>
<li>You still edit an existing file; your modifications would be erased by upgrading to a newer version of the plugin</li>
<li>It will confuse version control systems if you use one to retrieve the plugin</li>
<li>Your custom code is in the plugin directory, which is just illogical</li>
<li>You could chose no to ship any of the blank files, but the user would have to create all of them</li>
</ul>
<p>There is a very simple solution to overcome all that: the Symfony autoloader will pick classes from local folders (like the <code>lib</code> folder of your project) first.<br />
Which means you can just copy the <code>Penguin.class.php</code> file and customize it:</p>
<pre class="php"><span style="color: #808080; font-style: italic;"># Penguin.class.php your project's lib/ folder</span>
<span style="color: #000000; font-weight: bold;">class</span> Penguin <span style="color: #000000; font-weight: bold;">extends</span> pluginPenguin
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Linux is good<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p>If you don't use Symfony and/or a similar autoloader, there is another solution:</p>
<pre class="php"><span style="color: #808080; font-style: italic;"># Penguin.class.php in the sfHerdPlugin directory</span>
<span style="color: #b1b100;">require</span> <a href="http://www.php.net/dirname"><span style="color: #000066;">dirname</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #ff0000;">'/plugin/plugin'</span>.<a href="http://www.php.net/basename"><span style="color: #000066;">basename</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/is_readable"><span style="color: #000066;">is_readable</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/dirname"><span style="color: #000066;">dirname</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #ff0000;">'/../sfHerdPluginCustom/'</span>.<a href="http://www.php.net/basename"><span style="color: #000066;">basename</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>:
  <span style="color: #b1b100;">require</span> <a href="http://www.php.net/dirname"><span style="color: #000066;">dirname</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #ff0000;">'/../sfHerdPluginCustom/'</span>.<a href="http://www.php.net/basename"><span style="color: #000066;">basename</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">else</span>:
  <span style="color: #000000; font-weight: bold;">class</span> Penguin <span style="color: #000000; font-weight: bold;">extends</span> pluginPenguin
  <span style="color: #66cc66;">&#123;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #b1b100;">endif</span>;
&nbsp;</pre>
<pre class="php"><span style="color: #808080; font-style: italic;"># Penguin.class.php in the sfHerdPluginCustom directory (optional)</span>
<span style="color: #000000; font-weight: bold;">class</span> Penguin <span style="color: #000000; font-weight: bold;">extends</span> pluginPenguin
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Linux is good<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p>The cool aspect is that if you don't create any corresponding files in the <code>sfHerdPluginCustom</code> directory, it will still work perfectly.
<ol class="footnotes">
<li id="footnote_0_71" class="footnote">The Herd and Penguin classes are references to <a href="http://www.gotopp.org/">GOTO++</a>, a funny programming language.</li>
</ol>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/b7eLjc1-oGo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/06/extending-plugins-in-php-and-symfony/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/06/extending-plugins-in-php-and-symfony/</feedburner:origLink></item>
		<item>
		<title>PHP serialization optimization</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/uMoWh3wP_Uo/</link>
		<comments>http://laurent.bachelier.name/2009/05/php-serialization-optimization/#comments</comments>
		<pubDate>Thu, 07 May 2009 19:12:03 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[propel]]></category>
		<category><![CDATA[serialization]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=106</guid>
		<description><![CDATA[I recently had to use the serialize() function to store objects in Memcache.
However, I realized that a lot of these objects (Propel objects precisely) were unnecessarily huge when stored: they had a lot of properties with quite long names having their default class value.
That's when I realized I could use the __sleep() function to store [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:cb985b87930389fd304e9b23da8b87ac3e13f9ab'><p>I recently had to use the <code><a href="http://www.php.net/serialize">serialize</a>()</code> function to store objects in <a href="http://www.danga.com/memcached/">Memcache</a>.</p>
<p>However, I realized that a lot of these objects (<a href="http://propel.phpdb.org/">Propel</a> objects precisely) were unnecessarily huge when stored: they had a lot of properties with quite long names having their default class value.</p>
<p>That's when I realized I could use the <code>__sleep()</code> function to store only what I wanted. I gave up on using this function before as it would have been to hard to maintain it ...unless you use some meta-programming features of PHP to store only the variables not having their default value! That's what I did, and the results are a faster <code>unserialize()</code>, less memory usage, and no maintenance whatsoever.</p>
<p><span id="more-106"></span></p>
<p>Here it is:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Util
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> cmp<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$a</span>, <span style="color: #0000ff;">$b</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$a</span> === <span style="color: #0000ff;">$b</span> ? <span style="color: #cc66cc;">0</span> : <span style="color: #cc66cc;">1</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Penguin
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">function</span> __sleep<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// Get the name of the changed properties</span>
    <span style="color: #0000ff;">$vars</span> = <a href="http://www.php.net/array_keys"><span style="color: #000066;">array_keys</span></a><span style="color: #66cc66;">&#40;</span>
              array_udiff_assoc<span style="color: #66cc66;">&#40;</span>
                <a href="http://www.php.net/get_object_vars"><span style="color: #000066;">get_object_vars</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span><span style="color: #66cc66;">&#41;</span>,
                <a href="http://www.php.net/get_class_vars"><span style="color: #000066;">get_class_vars</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/get_class"><span style="color: #000066;">get_class</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,
                <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Util'</span>, <span style="color: #ff0000;">'cmp'</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#41;</span>
            <span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// Optional part: call the parent's __sleep() function if there is one</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/method_exists"><span style="color: #000066;">method_exists</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/get_parent_class"><span style="color: #000066;">get_parent_class</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">'__sleep'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
      <span style="color: #0000ff;">$vars</span> = <a href="http://www.php.net/array_merge"><span style="color: #000066;">array_merge</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$vars</span>, parent::__sleep<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$vars</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>If you use <code>unset()</code> on a default variable, my function will not detect it. Doing this would be a very bad idea anyway.</p>
<p>If your final object extends an object that has <em>private</em> properties, you will need to add my <code>__sleep()</code> function to it too. The good news is that Propel objects only have <em>protected</em> properties.</p>
<p><strong>Update:</strong> Unfortunately the <code>$_new</code> attribute of Propel's <code>BaseObject</code> is <em>private</em>, and set to <em>true</em> by default, which should not be the case for already saved objects (the ones you are likely to cache). You could either add it manually in your <code>__sleep()</code> function or use this <code>__wakeup()</code> function:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Penguin <span style="color: #000000; font-weight: bold;">extends</span> BaseObject
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">function</span> __wakeup<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
     <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">setNew</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>Though the proper way would be to add this to the <code>__sleep()</code> function:</p>
<pre class="php">&nbsp;
  <span style="color: #0000ff;">$vars</span> = <a href="http://www.php.net/array_merge"><span style="color: #000066;">array_merge</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\0</span>BaseObject<span style="color: #000099; font-weight: bold;">\0</span>_new&quot;</span>, <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\0</span>BaseObject<span style="color: #000099; font-weight: bold;">\0</span>_deleted&quot;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #0000ff;">$vars</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p>I wish there was a better way to do all this in PHP!</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/uMoWh3wP_Uo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/05/php-serialization-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/05/php-serialization-optimization/</feedburner:origLink></item>
		<item>
		<title>Symfony and lighttpd</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/Q9fS_dyQzQE/</link>
		<comments>http://laurent.bachelier.name/2009/04/symfony-and-lighttpd/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 19:29:24 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=92</guid>
		<description><![CDATA[I've seen some articles on how to configure lighttpd to serve a Symfony project, however they usually did at least one mistake:

Assuming that requests with periods ('.') are for static files (the period is a default separator in Symfony, and is extensively used in the new admin generators).
Ignoring parameters after a '?' (they are not [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:87cb62125a7e275147cf0edddf7bc9d4b5ce9e0d'><p>I've seen some articles on how to configure lighttpd to serve a Symfony project, however they usually did at least one mistake:</p>
<ul>
<li>Assuming that requests with periods ('<code>.</code>') are for static files (the period is a default separator in Symfony, and is extensively used in the new admin generators).</li>
<li>Ignoring parameters after a '<code>?</code>' (they are not widely used, except... in the new admin generators, and can be very useful if your application)</li>
</ul>
<p>For the first part, there is a much simpler solution to handle static files: most of them are in specific directories, except for a very limited number of ones.</p>
<p>My solution also handles assets published by plugins (you might want to edit the corresponding line to a more liberal one though).</p>
<p>You might want to add your <code>sitemap.xml.gz</code> or <code>robots.txt</code> to this list if you generate them statically.</p>
<p>For the second part, you simply have to match explicitly the '<code>?</code>' part.</p>
<p>Here is the magic:</p>
<pre class="lua">&nbsp;
alias.url = <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">&quot;/sf/&quot;</span> =&gt; <span style="color: #ff0000;">&quot;/home/web/symfony_12/data/web/sf/&quot;</span>
<span style="color: #66cc66;">&#41;</span>
&nbsp;
url.rewrite-once = <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">&quot;^/css/.+&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>, # directories with static files
  <span style="color: #ff0000;">&quot;^/js/.+&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>,
  <span style="color: #ff0000;">&quot;^/images/.+&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>,
  <span style="color: #ff0000;">&quot;^/uploads/.+&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>,
  <span style="color: #ff0000;">&quot;^/favicon<span style="color: #000099; font-weight: bold;">\.</span>ico$&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>, # static file example
  <span style="color: #ff0000;">&quot;^/sf[A-z]+Plugin.*&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>, # plugins
  <span style="color: #ff0000;">&quot;^/sf/.+&quot;</span> =&gt; <span style="color: #ff0000;">&quot;$0&quot;</span>, # symfony assets
  <span style="color: #ff0000;">&quot;^/backend<span style="color: #000099; font-weight: bold;">\.</span>php(/[^<span style="color: #000099; font-weight: bold;">\?</span>]*)(<span style="color: #000099; font-weight: bold;">\?</span>.*)?&quot;</span> =&gt; <span style="color: #ff0000;">&quot;/backend.php$1$2&quot;</span>, # allow access to another application
  <span style="color: #ff0000;">&quot;^(/[^<span style="color: #000099; font-weight: bold;">\?</span>]*)(<span style="color: #000099; font-weight: bold;">\?</span>.*)?&quot;</span> =&gt; <span style="color: #ff0000;">&quot;/index.php$1$2&quot;</span> # default application
<span style="color: #66cc66;">&#41;</span>
&nbsp;</pre>
<p>I guess the usage of periods in the rules also had the benefit of allowing the access to any alternative application automatically. With my solution you have to add each <code>appname.php</code> file manually, unless you use:</p>
<pre class="lua">&nbsp;
  <span style="color: #ff0000;">&quot;^/([a-z]+)<span style="color: #000099; font-weight: bold;">\.</span>php(/[^<span style="color: #000099; font-weight: bold;">\?</span>]*)(<span style="color: #000099; font-weight: bold;">\?</span>.*)?&quot;</span> =&gt; <span style="color: #ff0000;">&quot;/$1.php$2$3&quot;</span>, # any app <span style="color: #66cc66;">&#40;</span>prod<span style="color: #66cc66;">&#41;</span>
&nbsp;</pre>
<p>Or for allowing any environment:</p>
<pre class="lua">&nbsp;
  <span style="color: #ff0000;">&quot;^/([a-z_]+)<span style="color: #000099; font-weight: bold;">\.</span>php(/[^<span style="color: #000099; font-weight: bold;">\?</span>]*)(<span style="color: #000099; font-weight: bold;">\?</span>.*)?&quot;</span> =&gt; <span style="color: #ff0000;">&quot;/$1.php$2$3&quot;</span>, # any app <span style="color: #66cc66;">&#40;</span>any env<span style="color: #66cc66;">&#41;</span>
&nbsp;</pre>
<p>Note: your application must contain only lowercase letters, but you're free to adapt it to your own usage.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/Q9fS_dyQzQE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/04/symfony-and-lighttpd/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/04/symfony-and-lighttpd/</feedburner:origLink></item>
		<item>
		<title>CSS Naked Day</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/oaEZ3M4ilAU/</link>
		<comments>http://laurent.bachelier.name/2009/04/css-naked-day/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 13:35:29 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[standards]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=96</guid>
		<description><![CDATA[Today is CSS Naked Day!
My blog works perfectly without any CSS, of course; I often use Lynx to check websites I designed.
]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:a2fa2342cdbc883ee8bc8b6ff8af52d8f74d4c2c'><p>Today is <a href="http://naked.dustindiaz.com/">CSS Naked Day</a>!<br />
My blog works perfectly without any CSS, of course; I often use <a href="http://en.wikipedia.org/wiki/Lynx_(web_browser)">Lynx</a> to check websites I designed.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/oaEZ3M4ilAU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/04/css-naked-day/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/04/css-naked-day/</feedburner:origLink></item>
		<item>
		<title>Switching from BIND to PowerDNS in a few seconds</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/qtXP3l1uApA/</link>
		<comments>http://laurent.bachelier.name/2009/03/switching-from-bind-to-powerdns-in-a-few-seconds/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 19:39:36 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[bind]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[pdns]]></category>
		<category><![CDATA[powerdns]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[zone]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=62</guid>
		<description><![CDATA[Seconds, really.
First, why stop using BIND? For me it just happened because I couldn't understand why BIND wasn't working (again). However there are many other reasons to make the switch before it's too late. BIND has a bad security history, PowerDNS's code is more "modern" and its various parts are well-separated (for example, you are [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:de057f5c4b013e7a98c9e03132cf8e469a9ee2b1'><p>Seconds, really.</p>
<p>First, why stop using <a href="http://en.wikipedia.org/wiki/BIND">BIND</a>? For me it just happened because I couldn't understand why BIND wasn't working (again). However there are many other reasons to make the switch before it's too late. BIND has a bad security history, <a href="http://en.wikipedia.org/wiki/PowerDNS">PowerDNS</a>'s code is more "modern" and its various parts are well-separated (for example, you are not obligated to even <em>install</em> the recursor, it's another daemon).</p>
<p>PowerDNS now has a <a href="http://doc.powerdns.com/bindbackend.html">BIND zone backend</a>, and it works with both primary (master) and secondary (slave) zones. Before that, only database or other fancy backends were available; for hosting only some small domains it would be overkill and a pain to manage.<br />
However the documentation wasn't really clear. Here is how to do it.</p>
<p><span id="more-62"></span></p>
<h1>How to do it</h1>
<p>You should have this in your <code>pdns.conf</code> file:</p>
<pre class="tcl"><span style="color: #808080; font-style: italic;"># Start the bind backend (you can load multiple backends)</span>
launch=bind
<span style="color: #808080; font-style: italic;"># Path to your BIND named.conf</span>
bind-config=/etc/bind/named.conf
<span style="color: #808080; font-style: italic;"># PowerDNS will check if the zones are modified automatically. No need to reload the daemon!</span>
bind-check-interval=<span style="color: #ff4500;">300</span></pre>
<p>And... that's it, you're done.</p>
<p>But don't forget to set <code>allow-axfr-ips</code> with the IPs of the secondary DNS servers of your primary domains in <code>pdns.conf</code> (that's <code>allow-transfer</code> in <code>named.conf</code>).</p>
<h1>More details</h1>
<p>The only thing needed in <code>named.conf</code> are <code>zone</code> entries, anything else is ignored. For example:</p>
<pre class="tcl">zone <span style="color: #483d8b;">&quot;example.com&quot;</span> IN <span style="color: black;">&#123;</span>
    type slave;
    <span style="color: #008000;">file</span> <span style="color: #483d8b;">&quot;/etc/bind/sec/example.com.zone&quot;</span>;
    masters <span style="color: black;">&#123;</span> <span style="color: #ff4500;">1.3</span><span style="color: #ff4500;">.3</span><span style="color: #ff4500;">.7</span>; <span style="color: black;">&#125;</span>;
<span style="color: black;">&#125;</span>;
&nbsp;
zone <span style="color: #483d8b;">&quot;example.net&quot;</span> IN <span style="color: black;">&#123;</span>
    type master;
    <span style="color: #008000;">file</span> <span style="color: #483d8b;">&quot;/etc/bind/pri/example.net.zone&quot;</span>;
<span style="color: black;">&#125;</span>;</pre>
<p>If you want to create your first zone file, you can use the <a href="http://pgl.yoyo.org/adservers/bind-zone-file-creator.php">BIND zone file creator</a>.</p>
<p>I also encourage you to try out the <code>pdns_control</code>  tool that is bundled with PowerDNS.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/qtXP3l1uApA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/03/switching-from-bind-to-powerdns-in-a-few-seconds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/03/switching-from-bind-to-powerdns-in-a-few-seconds/</feedburner:origLink></item>
		<item>
		<title>Colophon</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/TKCxMFb2Zco/</link>
		<comments>http://laurent.bachelier.name/2009/03/colophon/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 23:53:01 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[colophon]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[themes]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=45</guid>
		<description><![CDATA[What did I use to build this blog? First of all, you will notice I am using WordPress. I looked briefly at the alternatives, but the thing that made me stick with WordPress is that they lack a lot of features and more importantly the WordPress community is amazing (numerous themes and plugins). Granted, a [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:e89c947e3e42eaa3a1b283406f34a3b33cd6a910'><p>What did I use to build this blog? First of all, you will notice I am using <a href="http://wordpress.org/">WordPress</a>. I looked briefly at the alternatives, but the thing that made me stick with WordPress is that they lack a lot of features and more importantly the WordPress community is amazing (numerous themes and plugins). Granted, a lot of plugins are badly written or out of date... but it's still better than nothing.<br />
Anyway, I discovered a pretty promising blog engine, <a href="http://zine.pocoo.org/">Zine</a>, written in Python and using the impressive <a href="http://www.sqlalchemy.org/">SQLAlchemy</a>.</p>
<p>The only thing I miss with WordPress is the ability to use another markup language in the posts; I can't stand <abbr title="What You See Is What You Get">WYSIWYG</abbr> editors but I don't like writing raw HTML either. Earliest versions supported <a href="http://en.wikipedia.org/wiki/Markdown">Markdown</a> but it has been dropped progressively.</p>
<p><span id="more-45"></span></p>
<h1>The Theme</h1>
<p>I used the <a href="http://themeshaper.com/thematic-for-wordpress/">Thematic Theme Framework</a>. There are many other Theme Frameworks for WordPress, like <a href="http://themehybrid.com/">Hybrid</a> or even <a href="http://getk2.com/">K2</a>. These theme frameworks usually come with very good HTML (semantic classes, microformats, SEO optimization, you name it) and a basic CSS. I wanted something light, and Hybrid's website annoying and clearly too greedy; K2 is amazing but a bit too much. I then created a <a href="http://wangenweb.com/2008/07/creating-wordpress-child-themes/">child theme</a>.</p>
<h1>The Plugins</h1>
<p>There are many plugins for WordPress; that's why it's easy to miss very good plugins. Here is what I use.</p>
<h2><abbr title="Search Engine Optimization">SEO</abbr></h2>
<p><a href="http://wordpress.org/extend/plugins/google-sitemap-generator/">Google XML Sitemaps</a> and <a href="http://wordpress.org/extend/plugins/all-in-one-seo-pack/">All-In-One SEO Pack</a>. They are really popular and vital plugins. I use SEO Pack mainly to disable indexing of anything that would lead to duplicate content (archive pages, etc.) and to insert my validation codes in the home pager header. <a href="http://wordpress.org/extend/plugins/redirection/">Redirection</a> can automatically create redirections if you change the <em>slug</em> of a post (and it can do much more too).<br />
By the way, you'll notice that my permalinks are different than the default; I didn't include the day number. I don't think users generally care for it.</p>
<h2>Stats</h2>
<p><a href="http://www.google.com/support/feedburner/bin/answer.py?answer=78483&topic=13252">FeedBurner FeedSmith</a> redirects the feed to FeedBurner, <a href="http://wordpress.org/extend/plugins/ultimate-google-analytics/">Ultimate Google Analytics</a>... well, you guess.</p>
<h2>Microformats</h2>
<p>Most microformats are already handled by the theme. <a href="http://wordpress.org/extend/plugins/wplicense/">WpLicense</a> includes a Creative Commons license information in the feed and page, <a href="http://wordpress.org/extend/plugins/microid/">MicroID</a> provides <a href="http://microid.org/">MicroID</a> for the blog, posts, and comments and <a href="http://wordpress.org/extend/plugins/xrds-simple/">XRDS Simple</a> is a requirement to run an <a href="http://openid.net/">OpenID</a> server.</p>
<h2>Publicity</h2>
<p><a href="http://wordpress.org/extend/plugins/sociable/">Sociable</a> provides links to popular social bookmarking services. <a href="http://wordpress.org/extend/plugins/wp-greet-box/">WP Greet Box</a> greets users and encourages them to subscribe to my RSS feed and vote for me me depending on where they come from.</p>
<h2>Antispam</h2>
<p><a href="http://wordpress.org/extend/plugins/simple-trackback-validation/">Simple Trackback Validation</a> just should be integrated with WordPress. <a href="http://wordpress.org/extend/plugins/wp-mollom/">Mollom</a> is like <a href="http://akismet.com/">Akismet</a> but better: it can use OpenIDs (reputation) and provides a captcha to recover your comment. <a href="http://wordpress.org/extend/plugins/httpbl/">http:BL</a> queries <a href="http://www.projecthoneypot.org/">Project Honeypot</a> (more about that later) to block spammers before they try to comment or even spider your site. <a href="http://wordpress.org/extend/plugins/tags/dofollow">DoFollow</a> rewards good commenters by removing the "nofollow" <code>rel</code> attribute on certain conditions.</p>
<h2>Markup</h2>
<p><a href="http://wordpress.org/extend/plugins/code-highlighter/">CodeHighlighter</a> for code syntax highlighting using <a href="http://qbnz.com/highlighter/">GeSHi</a>. <a href="http://wordpress.org/extend/plugins/wp-footnotes/">WP-Footnotes</a><sup>1</sup>.</p>
<h2>Pages</h2>
<p>I actually used only one of these three plugins but they are very useful and surprisingly unpopular; <a href="http://wordpress.org/extend/plugins/page-menu-editor/">Page Menu Editor</a>, <a href="http://wordpress.org/extend/plugins/page-links-to/">Page Links To</a> and <a href="http://wordpress.org/extend/plugins/exclude-pages/">Exclude Pages from Navigation</a>.</p>
<h2>Other</h2>
<p><a href="http://wordpress.org/extend/plugins/smart-archives-reloaded/">Smart Archives Reloaded</a> provides a really nice Archive page listing every post from the start. <a href="http://wordpress.org/extend/plugins/openid/">OpenID</a> allows commenters to prove it's really them commenting (plus, they get a nice icon) and users to login with an OpenID rather than a password. <a href="http://wordpress.org/extend/plugins/simple-tags">Simple Tags</a> introduces some nice additions to the standard WordPress tag system, like tag suggestion.
<ol class="footnotes">
<li id="footnote_0_45" class="footnote">Hello!</li>
</ol>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/TKCxMFb2Zco" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/03/colophon/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/03/colophon/</feedburner:origLink></item>
	</channel>
</rss>
