<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Erik Brännström</title>
	<atom:link href="http://blog.streambur.se/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.streambur.se</link>
	<description>Web development lovin&#039;</description>
	<lastBuildDate>Sat, 09 Apr 2011 13:56:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Xdebug in Netbeans on a MAMP setup</title>
		<link>http://blog.streambur.se/2011/04/xdebug-in-netbeans-on-a-mamp-setup/</link>
		<comments>http://blog.streambur.se/2011/04/xdebug-in-netbeans-on-a-mamp-setup/#comments</comments>
		<pubDate>Sat, 09 Apr 2011 11:07:21 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=195</guid>
		<description><![CDATA[I have been doing a lot of PHP development for my bachelor thesis over the last few months. We are working in a team of six and it is not always trivial to keep track of all the changes to the code, and debugging code you are not all that familiar with is a pain in the ass. To resolve my debugging issue I decided it was time I got Xdebug into the mix.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2011/04/xdebug-logo.png"><img class="alignleft size-full wp-image-205" title="xdebug-logo" src="http://blog.streambur.se/wp-content/uploads/2011/04/xdebug-logo.png" alt="" width="200" height="116" /></a>I have been doing a lot of PHP development for my bachelor thesis over the last few months. We are working in a team of six and it is not always trivial to keep track of all the changes to the code, and debugging code you are not all that familiar with is a pain in the ass. I am coding in <a title="NetBeans IDE" href="http://netbeans.org/index.html" target="_blank">Netbeans 7.0 beta 2</a> with MAMP Pro 1.9 taking care of the server. To resolve my debugging issue I decided it was time I got Xdebug into the mix. It should also be noted that I&#8217;m using PHP 5.3, but I believe all of this should work just the same for 5.2 if you just replace the version number wherever it appears.</p>
<p>MAMP actually comes bundled with Xdebug, though it is not enabled by default. The first thing I did was to upgrade the version of Xdebug to 2.1.0. I don&#8217;t think this is required, but it sure didn&#8217;t hurt. Just download the <a href="http://code.activestate.com/komodo/remotedebugging/" target="_blank">PHP Remote Debugging Client</a> from the the boys at ActiveState and replace the <em>xdebug.so</em> in your <em>/Applications/MAMP/bin/php5.3/lib/php/extensions/no-debug-non-zts-20090626</em> folder (the date on the end might be different, but just go with what you find!) with the one unzipped from the downloaded file.</p>
<p>The next step is to enable Xdebug which we do in the php.ini file. Open up MAMP, select File -&gt; Edit Template -&gt; &#8216;PHP 5.3.2 php.ini&#8217; from the menu and modify the end of the file so that it looks (somewhat) like the one below. This is just an example however, and these INI-settings are basically a mash-up of all the tips I found  while googling the matter. Especially note that the <em>xdebug.default_enable</em>, <em> xdebug.remote_autostart</em> and <em>xdebug.idekey</em> settings are not mentioned in  the <a title="HowToConfigureXDebug " href="http://wiki.netbeans.org/HowToConfigureXDebug" target="_blank">NetBeans Wiki&#8217;s guide</a>, so it might be that  they are not required. Also be really sure the Zend Optimizer line is commented out, since it apparently interferes with Xdebug.</p>
<pre>[xdebug]
xdebug.default_enable=1
zend_extension="/Applications/MAMP/bin/php5.3/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so"
xdebug.remote_enable=1
xdebug.remote_log="/var/log/xdebug.log"
xdebug.remote_host=localhost
xdebug.remote_handler=dbgp
xdebug.remote_port=9000
xdebug.remote_autostart=1
xdebug.idekey="netbeans-xdebug"

[Zend]
;MAMP_zend_optimizer_MAMP</pre>
<p>After this step I wasted a lot of time on trying to find out why NetBeans couldn&#8217;t connect to Xdebug. Finally I rebooted my computer and everything was suddenly working. My best guess is that this was due to a conflict on port 9000 (possibly with Skype). Feel free to try it out with only restarting the MAMP server but remember to do a full reboot if things still aren&#8217;t working.</p>
<p>By now you should be up and running. NetBeans debugging functionality is pretty straightforward, however you might want to check out the <a title="Debugging PHP Source Code in the NetBeans IDE " href="http://netbeans.org/kb/docs/php/debugging.html" target="_blank">official documentation</a> to get started. Hope this saves someone else a few hours, and feel free to share your tips in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2011/04/xdebug-in-netbeans-on-a-mamp-setup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Co-editing using PlainText / Dropbox</title>
		<link>http://blog.streambur.se/2011/01/co-editing-using-plaintext-dropbox/</link>
		<comments>http://blog.streambur.se/2011/01/co-editing-using-plaintext-dropbox/#comments</comments>
		<pubDate>Sat, 01 Jan 2011 22:39:21 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ios]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=182</guid>
		<description><![CDATA[Happy new year! Over the last six months I've become the proud owner of both an iPhone and an iPad. Indeed, the fanboy accusations are getting hard to dismiss. Anyhow, my fiancée also got an iPhone and I thought I should do something useful with that. The result? Instantly updated grocery lists (or classified government documents, if that's more up your alley).]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2011/01/plaintext-logo.png"><img class="size-full wp-image-183 alignleft" title="PlainmText logo" src="http://blog.streambur.se/wp-content/uploads/2011/01/Screen-shot-2011-01-01-at-Week-1-January-1-11.31.50-PM.png" alt="PlainText" width="107" height="106" /></a></p>
<p>Happy new year! Over the last six months I&#8217;ve become the proud owner of both an iPhone and an iPad. Indeed, the fanboy accusations are getting hard to dismiss. Anyhow, my fiancée also got an iPhone and I thought I should do something useful with that.</p>
<p>I guess most people have heard of the amazing (and free!) <a href="https://www.dropbox.com/referrals/NTkzNjAwMDk5?src=global0">Dropbox</a>. In short, it is a file sharing service that integrates directly with your file system. Simply drop a file into the Dropbox folder and &#8211; wham! &#8211; you can now access it via the web, a mobile application or another computer, or share files with your friends and family. Other applications can utilize this great feature, and one of those is <a href="http://www.hogbaysoftware.com/products/plaintext" target="_blank">PlainText</a>. It is an iOS text-editing application that syncs all files using Dropbox.</p>
<p>One lacking feature of PlainText though, is that it does not give you the option of sharing files and folders with others, which would be really useful for, say, grocery shopping. I realized it would be pretty sweet if whenever Emelie or I thought of something we needed to get at the store, we just wrote it down in an app and both of us would have instant access to the list, so it wouldn&#8217;t matter which one of us went shopping. Since PlainText uses Dropbox, this is in fact a rather simple thing to set up.</p>
<p>First of all I created a new folder in PlainText, since I want easy control over which files to share. This folder will be synced using Dropbox so after it has been created, manually share the folder with whomever you&#8217;d like either by right-clicking the folder on your computer or via the web interface. When you share a folder within another folder, the receiving user will have it appear at the lowest level in his or her Dropbox folder structure, so make sure they move the shared folder inside their PlainText folder.</p>
<p>And, voilà! Time to get the freaky co-editing started! If the folder does not show up, or disappears after it&#8217;s been shared, do a hard restart of the application on your device. It did the trick for me.</p>
<p>Do you have a nice Dropbox trick? Or simply know of a free app that does this same thing, only ten times better? Share in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2011/01/co-editing-using-plaintext-dropbox/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Empty inbox brings peace of mind</title>
		<link>http://blog.streambur.se/2010/08/empty-inbox-brings-peace-of-mind/</link>
		<comments>http://blog.streambur.se/2010/08/empty-inbox-brings-peace-of-mind/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 18:35:59 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=175</guid>
		<description><![CDATA[Let's cut the crap: I'm a fan-boy, plain and simple. I'm an Apple fan-boy and I'm a Google fan-boy. I love the simplicity of the products they create, and for the most part everything just works. I've been using Gmail since 2004 when it was still in closed beta and have never felt the need to use anything else. Somehow though, it took me almost six years to realize I was using it all wrong.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/08/400400839_f5b5bb0d16_m.jpg"><img class="alignleft size-full wp-image-176" title="400400839_f5b5bb0d16_m" src="http://blog.streambur.se/wp-content/uploads/2010/08/400400839_f5b5bb0d16_m.jpg" alt="" width="240" height="159" /></a> Let&#8217;s cut the crap: I&#8217;m a fan-boy, plain and simple. I&#8217;m an Apple fan-boy and I&#8217;m a Google fan-boy. I love the simplicity of the products they create, and for the most part everything just works. I&#8217;ve been using Gmail since 2004 when it was still in closed beta and have never felt the need to use anything else. Somehow though, it took me almost six years to realize I was using it all wrong.</p>
<p>For all this time I have been lazily reading and composing mail, using a few filters to get those incoming messages bagged and tagged but keeping every single e-mail in the inbox. It was only a month or so ago I realized the beauty of the Archive button, which was only sporadically used before. Since then I&#8217;ve got a very clear work-flow for dealing with all my mail.</p>
<p>The main goal is to keep your inbox empty. If you haven&#8217;t seen an empty inbox since the last trembling months of the last millennium you have no idea what you&#8217;re missing. It really gives a feeling of peace to see that nothingness stare back at you &#8211; no judgment for not replying, no expectation to be populated, just a blank slate. This is not always possible though, but most of the time I do manage to keep it empty.</p>
<p>Whenever a new e-mail pops in, I read it. Now, that&#8217;s not so hard? Once read I decide if I can answer it right at this moment, and if I can, I do. Thereafter I archive the conversation and move on. Archiving obviously also goes for informational messages that does not need any reply. Those e-mails that I expect to be able to answer in the next day or two are allowed to remain read in the inbox. That&#8217;s pretty much it!</p>
<p>Now, you may ask yourself &#8220;How about e-mails that I won&#8217;t be able to give an answer to until a further date?&#8221;. The answer to that is for you to reply immediately and write exactly that, and we are magically back to step one. For those really important e-mails that I might need to reference for longer periods of time I like to use the Star feature of Gmail.</p>
<p>Is the clutter-free inbox the way of the future or a pointless Getting Things Done-inspired waste of time? Go for comments.</p>
<p><em>Image by <a href="http://www.flickr.com/photos/epler/" target="_blank">Jim Epler</a>, released under Creative Commons.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/08/empty-inbox-brings-peace-of-mind/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Form protection revisited</title>
		<link>http://blog.streambur.se/2010/07/form-protection-revisited/</link>
		<comments>http://blog.streambur.se/2010/07/form-protection-revisited/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 21:44:16 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=159</guid>
		<description><![CDATA[About a month ago I wrote a post on how to protect your forms from double posting and CSRF attacks using nonce words in CodeIgniter. I realized pretty soon though that the code I posted wasn't as smooth or, in fact, as functional as it should be. So to save my own ass I though I should share this update with you guys.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/06/200px-Padlock.png"><img class="alignleft size-thumbnail wp-image-83" title="Padlock" src="http://blog.streambur.se/wp-content/uploads/2010/06/200px-Padlock-150x150.png" alt="Protect your forms" width="150" height="150" /></a>About a month ago I wrote a post on how to protect your forms from double posting and CSRF attacks using nonce words in CodeIgniter. I realized pretty soon though that the code I posted wasn&#8217;t as smooth or, in fact, as functional as it should be. So to save my own ass I though I should share this update with you guys.</p>
<p>I would like to put this in a less shameful way, but the fact is the library didn&#8217;t do what it was supposed to do. On every page refresh a new nonce was created, which indeed hindered an attempt to simply press the back button and resubmit. Problem was that if you submitted yet another time after the error message about the invalid nonce (well, you probably should word it differently to the end user) was displayed, the nonce passed validation.</p>
<p>That was the big problem which has been solved, but there&#8217;s more! First of all, the nonce now also contains a random element, further lessening the chance of an attacker being able to brute force the nonce word even though a successful attempt would be highly unlikely even before this addition.</p>
<p>Secondly, I&#8217;ve made some convenient changes to how to use this extension. The hidden field is now automatically output when you use the <strong>form_open</strong> function, and if you&#8217;d like to do it manually you should be able to figure it out yourself. Also the <strong>run</strong> method has been extended to mark a nonce as used after successful validation, so you don&#8217;t have to do it manually in the controller.</p>
<p>So this is the code you&#8217;ll need:</p>
<pre class="brush: php; title: ;">
/*
 * Helper (helpers/MY_form_helper.php)
 */
function form_open($action = '', $attributes = '', $hidden = array()) {
    $CI = &amp; get_instance();

    if ($attributes == '') {
        $attributes = 'method=&quot;post&quot;';
    }

    $action = ( strpos($action, '://') === FALSE) ? $CI-&gt;config-&gt;site_url($action) : $action;

    $form = '&lt;form action=&quot;' . $action . '&quot;';
    $form .= _attributes_to_string($attributes, TRUE);
    $form .= '&gt;';

    if($CI-&gt;form_validation-&gt;has_nonce()) {
        $value = set_value('nonce');
        if($value == '')
            $value = $CI-&gt;form_validation-&gt;create_nonce();
        $hidden['nonce'] = set_value('nonce', $value);
    }

    if (is_array($hidden) &amp;&amp; count($hidden) &gt; 0) {
        $form .= form_hidden($hidden);
    }

    return $form;
}

/*
 * Library (libraries/MY_Form_validation.php)
*/
class MY_Form_validation extends CI_Form_Validation {
    private $use_nonce = false;

    function __construct() {
        parent::__construct();
    }

    /**
     * Create a new unique nonce, save it to the current session and return it.
     */
    public function create_nonce() {
        $nonce = md5(rand() . $this-&gt;CI-&gt;input-&gt;ip_address() . microtime());
        $this-&gt;CI-&gt;session-&gt;set_userdata('nonce', $nonce);
        return $nonce;
    }

    public function has_nonce() {
        return $this-&gt;use_nonce;
    }

    public function run($group = '') {
        $result = parent::run($group);
        if($result === true) {
            $this-&gt;save_nonce();
        }
        return $result;
    }

    /**
     * Mark the nonce sent from the form as already used.
     */
    private function save_nonce() {
        $this-&gt;CI-&gt;session-&gt;set_userdata('old_nonce', $this-&gt;set_value('nonce'));
    }

    /**
     * Set form validation rules for the nonce.
     */
    function nonce() {
        $this-&gt;use_nonce = true;
        $this-&gt;set_rules('nonce', 'Nonce', 'required|valid_nonce');
    }

    /**
     * Make sure the nonce is valid.
     */
    function valid_nonce($str) {
        return ($str == $this-&gt;CI-&gt;session-&gt;userdata('nonce') &amp;&amp;
                $str != $this-&gt;CI-&gt;session-&gt;userdata('old_nonce'));
    }
}
</pre>
<p>All you have to do now is open the form with <strong>form_open</strong> in your view, load the library in the controller and call the <strong>nonce</strong> method. That should do it! A remaining potential problem is that this will not work with more than one form at a time, though I&#8217;ll have to leave that as homework for you guys. Comments are open!</p>
<p><em>Image from the <a href="http://www.openclipart.org/" target="_blank">Open Clip Art  Library</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/07/form-protection-revisited/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP vs. JavaScript</title>
		<link>http://blog.streambur.se/2010/06/php-vs-javascript/</link>
		<comments>http://blog.streambur.se/2010/06/php-vs-javascript/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 17:45:42 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=130</guid>
		<description><![CDATA[I love the rapid development of the technological wonder that is the Internet and it's standards. The early nineties brought us static HTML pages which, but as time moved on more and more processing took place at the servers with a variety of server-side languages. However during the last few years much processing has been transferred to the browser using Javascript. This has meant that the majority of all browsers have gotten along for the ride and spent a lot of time speeding up the execution of these scripts. Out of curiosity I decided to compare the time it takes to perform a few standard actions in both JS and PHP.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/06/phpjs.png"><img class="alignleft size-full wp-image-153" title="php.js" src="http://blog.streambur.se/wp-content/uploads/2010/06/phpjs.png" alt="php.js" width="170" height="90" /></a>I love the rapid development of the technological wonder that is the Internet and its standards. The early nineties brought us static HTML pages which, but as time moved on more and more processing took place at the servers with a variety of server-side languages. However during the last few years much processing has been transferred to the browser using Javascript. This has meant that the majority of all browsers have gotten along for the ride and spent a lot of time speeding up the execution of these scripts. Out of curiosity I decided to compare the time it takes to perform a few standard actions in both JS and PHP.</p>
<p>To compare the same functionality in the two languages I used the really awesome <a href="http://phpjs.org/" target="_blank">php.js</a> library, which sole purpose is to replicate as many PHP functions as possible using only Javascript. The tests were then run three times each in two different browsers, Firefox 3.6.6 and Opera 10.54, on my MacBook (Intel Core 2 Duo 2.4 GHz with 4 GB of RAM). The values presented are the average of these runs (for PHP I averaged all the six results).</p>
<table style="border: 1px solid #ccc; padding: 1em; margin: 1em 0;" width="100%">
<thead>
<tr>
<td style="font-weight: bold;" width="36%">Test</td>
<td style="font-weight: bold;" width="18%">PHP</td>
<td style="font-weight: bold;" width="18%">Firefox 3.6.6</td>
<td style="font-weight: bold;" width="18%">Opera 10.54</td>
</tr>
</thead>
<tbody>
<tr>
<td>Generate 10 000 MD5 hashes</td>
<td>0.0115 s</td>
<td>3.6770 s</td>
<td>0.7013 s</td>
</tr>
<tr>
<td>Generate 10 000 SHA1 hashes</td>
<td>0.0136 s</td>
<td>0.8553 s</td>
<td>0.5703 s</td>
</tr>
<tr>
<td>Square root of 100 000 integers</td>
<td>0.0481 s</td>
<td>0.0017 s</td>
<td>0.0033 s</td>
</tr>
<tr>
<td>Sum values from 30 000 objects</td>
<td>0.0220 s</td>
<td>0.0010 s</td>
<td>0.0020 s</td>
</tr>
<tr>
<td>Sort an array of 30 000 random integers</td>
<td>0.0222 s</td>
<td>0.0343 s</td>
<td>0.0273 s</td>
</tr>
</tbody>
</table>
<p>PHP really kicks ass when it comes to hashing, being about 60 times faster than Opera and a whooping 320 times faster than Firefox on the MD5 hashes. When it comes to calculating the square root it&#8217;s not as great though. Opera is about 14 times as fast and Firefox is twice as fast as Opera, so if you&#8217;re gonna be crunching numbers you might want to consider letting your users&#8217; browser do the heavy lifting.</p>
<p>For the summation test I created an array of 30 000 objects with two attributes, one name and one value, and the same array was used for Javascript by JSON-encoding the PHP variable. Javascript won this round as well, however, to be fair, my guess is that the reason for this is that JS objects have less overhead than their PHP counterparts and not so much it&#8217;s mathemagical powers (though that would go well with the square root awesomeness).</p>
<p>Lastly the sorting of an array. Once again the same array was used for both languages, but this time it&#8217;s a win for PHP. It&#8217;s a close call though, and especially the Javascript powerhouse that is Opera is not far behind.</p>
<p>So this is not the most scientific test around, but I still think the  results are pretty interesting. Comments are open, any great ideas of how we can use this for web development or did I just waste five minutes your time?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/06/php-vs-javascript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>What&#8217;s coming in Firefox.next?</title>
		<link>http://blog.streambur.se/2010/06/whats-coming-in-firefox-next/</link>
		<comments>http://blog.streambur.se/2010/06/whats-coming-in-firefox-next/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 14:55:09 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=110</guid>
		<description><![CDATA[I guess most of you might have seen the mockups for the UI redesign planned for Firefox. It's about time something was done about it, not because it's currently ugly per se, just not as good-looking as the opposition. I though I'd give you a break-down of some other changes we can look forward to in the next milestone for the best browser in the world (now pay up Mozilla!).]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/06/firefox-logo.png"><img class="alignleft size-full wp-image-126" title="firefox-logo" src="http://blog.streambur.se/wp-content/uploads/2010/06/firefox-logo.png" alt="Mozilla Firefox" width="150" height="150" /></a>I guess most of you might have seen the mockups for the UI redesign planned for Firefox (<a href="https://wiki.mozilla.org/Firefox/4.0_Mac_Theme_Mockups" target="_blank">Mac</a>, <a href="https://wiki.mozilla.org/Firefox/4.0_Windows_Theme_Mockups" target="_blank">Windows</a> and <a href="https://wiki.mozilla.org/Firefox/4.0_Linux_Theme_Mockups">Linux</a>). It&#8217;s about time something was done about it, not because it&#8217;s currently ugly per se, just not as good-looking as the opposition. I though I&#8217;d give you a break-down of some other changes we can look forward to in the next milestone for the best browser in the world (now pay up Mozilla!).</p>
<p>According to the Mozilla wiki, the first beta will be released tomorrow, but after running the nightlies I have my doubts about it. In any case it seems unlikely we get to admire the overhauled UI in the very near feature. The nightly releases includes a choice to move the <strong>tabs on top</strong>, however it looks really crappy at the moment (none of that <a href="http://arstechnica.com/apple/news/2009/02/hands-on-safari-4-beta-fast-mixes-polish-rough-ui-edges.ars" target="_blank">Safari 4 beta goodness</a> which Apple gaveth and tooketh) and besides that I haven&#8217;t noticed any design changes.</p>
<p>Another feature that&#8217;s missing from the alpha but which is likely to make an entrance in the final product is <a href="https://jetpack.mozillalabs.com/" target="_blank">Jetpack</a>, a new plugin architecture based on web standards. <strong>Jetpack</strong> is supposed to be more lightweight and won&#8217;t require a restart to start working.</p>
<p>Mac-users out there should all rejoice! <strong>Out-of-process-plugins</strong> are coming to us as well, a feature brought to Windows and Linux users with release 3.6.4. It has been said that version 4.0 would bring full tab process separation, however it seems to me it&#8217;s been rather quite on that front lately, so my guess is OOPP will have to do for now as it takes care of a large portion of the crashes. Though as we are moving away from plugins and towards standardized formats such as <a href="http://en.wikipedia.org/wiki/WebGL" target="_blank">WebGL</a>, JavaScript and HTML5, I do believe separating tab processes is inevitable.</p>
<p>Oh, and more UI updates! The <strong>add-on manager</strong> has been moved from an annoying dialog to a super-sexy tab. Well, a tab at least. Some work still remains, but it looks good and I personally appreciate the tabbed approach. Enter about:addons in the location bar and &#8211; bam! Speaking of the the Awesome Bar, a neat little feature that has been added is <strong>Switch-to-tab</strong>. For those of us having trouble keeping track of all open tabs, it&#8217;s not unusual to open up the same page twice. Now the Awesome Bar will also search your open tabs and allow you to simply switch to another tab.</p>
<p>For web developers, I&#8217;d say the most influential features are the additions  of <a href="http://en.wikipedia.org/wiki/WebM" target="_blank">WebM</a> video format, WebGL, CSS transitions, better HTML5 support,  <a href="http://dev.w3.org/html5/websockets/" target="_blank">Web Sockets</a> and <a href="http://www.w3.org/TR/IndexedDB/" target="_blank">IndexedDB</a>. As usual it will take some time until we can  actually make good use of these additions for most sites, but the first  step must always be taken by the browser developers.</p>
<p>My hope is that we will also see the integration of <a href="https://mozillalabs.com/sync/" target="_blank">Mozilla Sync</a>, previously called Weave, the syncing application which along with <a href="http://www.mozilla.com/mobile/" target="_blank">Firefox Mobile</a> and <a href="http://blog.mozilla.com/blog/2010/05/26/firefox-home-coming-soon-to-the-iphone/" target="_blank">Firefox Home</a> will really help spread the Mozilla love across platforms.</p>
<p><strong>EDIT</strong>: The previously mentioned Account Manager seems <a href="http://hacks.mozilla.org/2010/04/account-manager-coming-to-firefox/">way cooler</a> than I originally thought! Basically it will allow the browser to handle registrations on sites.</p>
<p>I am not in any way affiliated with Mozilla, and since Firefox 4.0 hasn&#8217;t even reached beta yet, much could still happen. I do, however, hope this made you as excited as I am about Firefox.next!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/06/whats-coming-in-firefox-next/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t forget me, cookie!</title>
		<link>http://blog.streambur.se/2010/06/dont-forget-me-cookie/</link>
		<comments>http://blog.streambur.se/2010/06/dont-forget-me-cookie/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 16:34:48 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=97</guid>
		<description><![CDATA[Most websites where authentication is required to perform certain actions have the option of remembering your credentials. Convenient, indeed, but bypassing the user input phase of the login means some other type of identifier needs to be stored locally which could pose a severe security risk.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/06/65345233_bd94e7347e.jpg"><img class="alignleft size-thumbnail wp-image-100" title="Cookies" src="http://blog.streambur.se/wp-content/uploads/2010/06/65345233_bd94e7347e-150x150.jpg" alt="" width="150" height="150" /></a>Most websites where authentication is required to perform certain actions have the option of remembering your credentials. Convenient, indeed, but bypassing the user input phase of the login means some other type of identifier needs to be stored locally which could pose a severe security risk.</p>
<p>My first attempt at this &#8211; and please remember this was a long, looong time ago, in a simpler time &#8211; was to simply store the username and password in a cookie. Yes, that&#8217;s right, store the user&#8217;s credentials in plain text. The security concerns are obvious, a simple cookie theft would give the attacker everything he needs without having to think twice, and as if that wasn&#8217;t enough there is a high risk that the same credentials can be used to access other sites since very few people actually use different passwords for every site they register on. Luckily this site never reached an audience..</p>
<p>By storing the password hash we will at least take care of the leaked credentials issue, as long as we use a decent hash algorithm and salt the password properly (a simple md5 is not good enough, but more on this another time), thereby taking the likes of simple dictionary attacks out of the equation. The attacker can still access the account however.</p>
<p>Fact is that a compromised &#8220;remember me&#8221;-cookie will always allow an attacker to gain access to the account to which the cookie belongs. What we want to do is mitigate the impact. For example, we want to make sure that a malicious user cannot access someone else&#8217;s account and lock them out by changing the password. For these types of actions that concern the privacy and security of the user we want to make sure that the authenticated user actually knows the password. As long as we do this, the above is a pretty decent solution.</p>
<p>An even better, though slightly more advanced, solution is to never even store the password, hashed or not, in the cookie. Instead a randomly generated <em>token</em> can be stored in the client cookie as well as in the application database upon login. The next time that same browser visits the site the token and username/user ID, whichever you prefer, from the cookie can be checked against the server and if they match we have a valid login. This is a very brief summary of the points made in Charles Miller&#8217;s post <a href="http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/" target="_blank">Persistent Login Cookie Best Practice</a> and Barry Jaspan&#8217;s improvement of the same in <a href="http://jaspan.com/improved_persistent_login_cookie_best_practice" target="_blank">Improved Persistent Login Cookie Best Practice</a>. This is about as safe as you can get as far as remembered logins go.</p>
<p>The point I really want to make is that there is no perfect solution for this and you should bear in mind that for any site requiring a high level of security a &#8220;remember me&#8221;-option is a big no-no, plain and simple. For any other site it&#8217;s a decision that must be made by you as a developer, weighting user convenience against any security implications.</p>
<p><em>Image by <a href="http://www.flickr.com/photos/ilmungo/" target="_blank">ilmungo</a>, licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" target="_blank">Creative Commons</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/06/dont-forget-me-cookie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No-nonsense protection using a nonce</title>
		<link>http://blog.streambur.se/2010/06/no-nonsense-protection-using-a-nonce/</link>
		<comments>http://blog.streambur.se/2010/06/no-nonsense-protection-using-a-nonce/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 16:44:50 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=75</guid>
		<description><![CDATA[In a web application for record collectors I wrote a few years ago I recently had to deal with users who added the same record hundreds of times. I did use the PRG, or Post/Redirect/Get, pattern which means that you always redirect the user after a post request so that a simple reload won't resubmit the same data. This prevents users from mistakenly resubmitting, but by pressing the back-button the problem re-emerges. The solution is called a nonce.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/06/200px-Padlock.png"><img class="alignleft size-full  wp-image-83" title="Padlock" src="http://blog.streambur.se/wp-content/uploads/2010/06/200px-Padlock.png" alt="Protect your forms" width="200" height="200" /></a><br />
<strong>UPDATE:</strong> A new and improved version of this extension can be found in my post <a href="http://blog.streambur.se/2010/07/form-protection-revisited/" target="_self">Form protection revisited</a>!</p>
<p>In a web application for record collectors I wrote a few years ago I recently had to deal with users who added the same record hundreds of times. I did use the PRG, or Post/Redirect/Get, pattern which means that you always redirect the user after a post request so that a simple reload won&#8217;t resubmit the same data. This prevents users from mistakenly resubmitting, but by pressing the back-button the problem re-emerges. The solution is called a <em>nonce</em>.</p>
<p>Actually, the use of a nonce also prevents an attack called <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" target="_blank">CSRF</a>, Cross-Site Request Forgery. Without going into detail, this means a malicious site can potentially perform CRUD operations with your credentials on a site you are currently logged in to. The idea to prevent this is to generate a nonce word that is sent with the form and stored at the server, making sure that the request is made using our form. This is basically what we wish to do:</p>
<ol>
<li>Generate nonce</li>
<li>Save nonce in a session variable</li>
<li>Add a hidden form field containing the nonce</li>
<li>Validate data and nonce</li>
<li>If nonce is valid, handle data and mark nonce as inactive</li>
</ol>
<p>The key here is the validation of the nonce. There are two things to consider, one is that we should not allow the same form to be posted twice and the other is that the form must know what the current nonce is. This means for every request we need to have the current and, if it exists, old nonce saved in the user&#8217;s session. Also note I am assuming the sessions are stored in a database, since if they are not you probably have bigger problems.</p>
<p>To solve this problem I have extended the CodeIgniter Form Validation library so that it can handle this extra layer of security.</p>
<pre class="brush: php; title: ;">
class MY_Form_Validation extends CI_Form_Validation {

	function __construct()
	{
		parent::__construct();
	}

    /**
     * Create a new unique nonce, save it to the current session and return it.
     *
     * @return string
     */
    function create_nonce()
    {
        $nonce = md5('nonce' . $this-&gt;CI-&gt;input-&gt;ip_address() . microtime());
        $this-&gt;CI-&gt;session-&gt;set_userdata('nonce', $nonce);
        return $nonce;
    }

    /**
     * Mark the nonce sent from the form as already used.
     */
    function save_nonce()
    {
        $this-&gt;CI-&gt;session-&gt;set_userdata('old_nonce', $this-&gt;set_value('nonce'));
    }

    /**
     * Set form validation rules for the nonce.
     */
    function nonce()
    {
        $this-&gt;set_rules('nonce', 'Nonce', 'required|check_nonce');
    }

 	/**
	 * Validation rule for making sure the nonce is valid.
	 *
	 * @access	public
	 * @param	string
     * @param	last used nonce
	 * @return	bool
	 */
	function check_nonce($str)
	{
        return ($str == $this-&gt;CI-&gt;session-&gt;userdata('nonce') &amp;&amp;
                $str != $this-&gt;CI-&gt;session-&gt;userdata('old_nonce'));
	}

}
</pre>
<p>Also, I extended the form helper to include a function for generating a new hidden form field with a unique nonce:</p>
<pre class="brush: php; title: ;">
/**
 * Generates a hidden field containing a nonce.
 *
 * @access	public
 * @return	string
 */
if ( ! function_exists('form_nonce'))
{
	function form_nonce()
	{
        $CI =&amp; get_instance();
        $CI-&gt;load-&gt;library('form_validation');
		$field = '&lt;input type=&quot;hidden&quot; name=&quot;nonce&quot; value=&quot;'
            . $CI-&gt;form_validation-&gt;set_value('nonce', $CI-&gt;form_validation-&gt;create_nonce())
            . '&quot; /&gt;';
        return $field;
	}
}
</pre>
<p>Last but not least I&#8217;ll show you how to use it in a controller method, in this case called add.</p>
<pre class="brush: php; title: ;">
	function add()
	{
		$this-&gt;load-&gt;library('form_validation');
		// Set validation rules here..
        $this-&gt;form_validation-&gt;nonce();

		if ($this-&gt;form_validation-&gt;run() !== FALSE) { // If validation has completed
            $this-&gt;form_validation-&gt;save_nonce();
			// Handle the validated post request
			redirect('controller/method');
		}
	}
</pre>
<p>This is not a subject I&#8217;d consider myself to be an expert in, so any input on the validity of this library is greatly appreciated. This is something that might very well get included in future versions of CodeIgniter, and it should, but until then I hope this is a good alternative.</p>
<p><em>Image from the <a href="http://www.openclipart.org/" target="_blank">Open Clip Art Library</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/06/no-nonsense-protection-using-a-nonce/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Simple date validation</title>
		<link>http://blog.streambur.se/2010/06/simple-date-validation/</link>
		<comments>http://blog.streambur.se/2010/06/simple-date-validation/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 15:19:47 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=59</guid>
		<description><![CDATA[CalendarDate validation usually means regular expressions, and regular expressions usually means headache. All in all, I do think that PHP's date handling is pretty sweet, but native validation is still lacking. With PHP 5.3 though, we are one step closer thanks to a new function with the infinitely long name date_parse_from_format. I'm going to show you how it can be used to create a validation function for any PHP date format.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.streambur.se/wp-content/uploads/2010/06/Crystal_Clear_app_date.png"><img class="alignleft size-full wp-image-66" title="Crystal Clear Calendar" src="http://blog.streambur.se/wp-content/uploads/2010/06/Crystal_Clear_app_date.png" alt="Calendar" width="128" height="128" /></a>Date validation usually means regular expressions, and regular expressions usually means headache. All in all, I do think that PHP&#8217;s date handling is pretty sweet, but native validation is still lacking. With PHP 5.3 though, we are one step closer thanks to a new function with the infinitely long name <a href="http://php.net/manual/en/function.date-parse-from-format.php">date_parse_from_format</a>. I&#8217;m going to show you how it can be used to create a validation function for any PHP date format.</p>
<p>So, the date_parse_from_format takes a date format and a string and parses the date to an associative array. Along with this I used the native <a href="http://php.net/manual/en/function.checkdate.php">checkdate</a> which takes the argument month, day and year and tells you whether or not it is a valid date.</p>
<pre class="brush: php; title: ;">
class MY_Form_Validation extends CI_Form_Validation {

	function __construct()
	{
		parent::__construct();
	}

	/**
	 * Validate date according to the specified format.
	 *
	 * @access	public
	 * @param	string
     * @param	date format
	 * @return	bool
	 */
	function valid_date($str, $format)
	{
        $date = date_parse_from_format($format, $str);
        return checkdate($date['month'], $date['day'], $date['year']);
	}

}
</pre>
<p>The valid_date function can be used by anyone sporting a PHP 5.3 install on their web host. Since I&#8217;m using CodeIgniter I simply put this function in MY_Form_Validation, which means I can easily use this function like any standard CI validation function, i.e.</p>
<pre class="brush: php; title: ;">

$this-&gt;form_validation-&gt;set_rules('birth', 'Birthday', 'valid_date[d-m-Y]');
</pre>
<p>This is a really handy trick for those otherwise (for me, at least) nasty date validations.</p>
<p><em>Image from <a href="http://www.everaldo.com/crystal/" target="_blank">Crystal Clear</a> icon set by Everaldo Coelho.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/06/simple-date-validation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fallback and relax</title>
		<link>http://blog.streambur.se/2010/06/fallback-and-relax/</link>
		<comments>http://blog.streambur.se/2010/06/fallback-and-relax/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 13:32:21 +0000</pubDate>
		<dc:creator>Erik Brännström</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[codeigniter]]></category>

		<guid isPermaLink="false">http://blog.streambur.se/?p=36</guid>
		<description><![CDATA[I recently finished a project for a client where a large part of  the site was made up of static pages. The obvious approach for this is  to create controllers and methods to load these views, meaning that the method team() in controller Football would load the view  views/football/team.php and be done with it. Is there a better way?]]></description>
			<content:encoded><![CDATA[<p>I recently finished a project for a client in CodeIgniter where a large part of  the site was made up of static pages. The obvious approach for this is  to create controllers and methods to load these views, meaning that the method team() in controller Football would load the view views/football/team.php and be done with it.</p>
<p>This, no offense, seemed stupid, so I decided to create a fallback controller that would have the sole task of dealing with unmatched requests. In other words, if the current URL can’t be matched to a controller method,  the request will be dispatched to the specified controller. In the example of the client site, this would then load the view who&#8217;s folder structure and filename matched the URL (see Football example above), but it could pretty much be tasked to deal with anything from error logging to paying your taxes.﻿</p>
<pre class="brush: php; title: ;">
&lt;?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

class MY_Router extends CI_Router {

    function MY_Router() {
        parent::CI_Router();

        log_message('debug', &quot;Custom Router Class Initialized&quot;);
    }

 	/**
	 * Validates the supplied segments.  Attempts to determine the path to
	 * the controller.
	 *
	 * @access	private
	 * @param	array
	 * @return	array
	 */
	function _validate_request($segments)
	{
		// Does the requested controller exist in the root folder?
		if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
		{
			return $segments;
		}

		// Is the controller in a sub-folder?
		if (is_dir(APPPATH.'controllers/'.$segments[0]))
		{
			// Set the directory and remove it from the segment array
			$this-&gt;set_directory($segments[0]);
			$segments = array_slice($segments, 1);

			if (count($segments) &gt; 0)
			{
				// Does the requested controller exist in the sub-folder?
				if ( ! file_exists(APPPATH.'controllers/'.$this-&gt;fetch_directory().$segments[0].EXT))
				{
					show_404($this-&gt;fetch_directory().$segments[0]);
				}
			}
			else
			{
				$this-&gt;set_class($this-&gt;default_controller);
				$this-&gt;set_method('index');

				// Does the default controller exist in the sub-folder?
				if ( ! file_exists(APPPATH.'controllers/'.$this-&gt;fetch_directory().$this-&gt;default_controller.EXT))
				{
					$this-&gt;directory = '';
					return array();
				}

			}

			return $segments;
		}

		// Can't find the requested controller...
		if( isset($this-&gt;routes['fallback_controller']) AND $this-&gt;routes['fallback_controller']) {
			$uri = explode('/', strtolower($this-&gt;routes['fallback_controller']));
			$uri = array_merge($uri, $segments);
			$this-&gt;_set_request($uri);
			return $uri;
		} else {
			show_404($segments[0]);
		}
	}

}
</pre>
<p>Most of the code above is copied from the core Router class, the only thing changed is below the last comment. This method does exactly what the PHPdoc says &#8211; it validates a request and decides which controller should be responsible for it. Normally though, it will just display the 404 page if no matching controller is found, but this is where our magic happens. We just check if a fallback controller has been set and if so, load it with any arguments from the URI.</p>
<p>Easy enough right? So all that remains is setting the fallback, which is done in application/config/routes.php where we add the following line (with the choice of controller up to you of course):</p>
<pre class="brush: php; title: ;">$route['fallback_controller'] = &quot;loader/load&quot;;</pre>
<p>I&#8217;ll leave writing the actual controller to you guys though.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.streambur.se/2010/06/fallback-and-relax/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

