<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    
    <title>&lt;?paul</title>
    <link>http://blog.preinheimer.com/</link>
    <description>Paul Reinheimer</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.5.3 - http://www.s9y.org/</generator>
    <pubDate>Fri, 04 May 2012 01:34:44 GMT</pubDate>

    <image>
        <url>http://blog.preinheimer.com/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: &lt;?paul - Paul Reinheimer</title>
        <link>http://blog.preinheimer.com/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>Impressed</title>
    <link>http://blog.preinheimer.com/index.php?/archives/382-Impressed.html</link>
            <category>Op-Ed</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/382-Impressed.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=382</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=382</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;I&#039;ve used countless password/license key reminder forms, probably hundreds. They&#039;re generally horrible, clearly tacked on at the last second by an intern.&lt;/p&gt;

&lt;p&gt;The one I used to request that &lt;a href=&quot;http://macromates.com/&quot;&gt;Macromates&lt;/a&gt; resend my license key for Textmate was phenomenal. After confirming that it had resent both my license keys, it provide me with links to the relevant sections of their mail log, to help me understand if there was any problems with delivery.&lt;/p&gt;

&lt;p&gt;It was an incredibly helpful example of true craftsmanship.&lt;br /&gt;

I&#039;m impressed. Kudos.&lt;/p&gt;

&lt;!-- s9ymdb:40 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;500&quot; height=&quot;586&quot;  src=&quot;http://blog.preinheimer.com/uploads/00000034.png&quot;  alt=&quot;&quot; /&gt;
 
    </content:encoded>

    <pubDate>Thu, 03 May 2012 21:34:44 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/382-guid.html</guid>
    
</item>
<item>
    <title>What Busy Means</title>
    <link>http://blog.preinheimer.com/index.php?/archives/381-What-Busy-Means.html</link>
            <category>Op-Ed</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/381-What-Busy-Means.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=381</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=381</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;Last week I asked a barista at Starbucks when they’re most and least busy. She quickly shared a few times with me; I thanked her and sat down. Thinking about it, the times she gave me differed radically from my own experiences. Pondering further I realized that we were using the word “busy” differently: Busy for me meant that the tables were full, and I wasn’t going to be able to come in and work, busy for her meant customers or transactions per minute. &lt;/p&gt;

&lt;p&gt;There’s a lesson here, and one I want to learn from. It’s incredibly easy to talk past someone, and make assumptions about understanding. &lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 29 Apr 2012 20:19:54 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/381-guid.html</guid>
    
</item>
<item>
    <title>Lytro</title>
    <link>http://blog.preinheimer.com/index.php?/archives/380-Lytro.html</link>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/380-Lytro.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=380</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=380</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;I love photography, I own a bunch of cameras, and have managed to lose a few along the way. When the &lt;a href=&quot;http://www.lytro.com/&quot;&gt;Lytro&lt;/a&gt; was announced a while back I was quite interested, and with a reasonable price point, I pre-ordered. It&#039;s arrived, and I&#039;ve had a few chances to play with it. Including last night while playing &lt;a href=&quot;http://www.amazon.com/gp/product/B000809OAO?ie=UTF8&amp;tag=preinheimerco-20&amp;linkCode=shr&amp;camp=213733&amp;creative=393185&amp;creativeASIN=B000809OAO&amp;ref_=sr_1_2&amp;qid=1333934392&amp;sr=8-2&quot;&gt;A ticket to Ride&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Sample Images&lt;/h3&gt;
&lt;p&gt;
Cards &amp;amp; Trains (click for larger image)&lt;br /&gt;
&lt;a class=&quot;serendipity_image_link&quot;  href=&#039;http://blog.preinheimer.com/uploads/Lytro-TTR-Cards.jpg&#039;&gt;&lt;!-- s9ymdb:35 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;110&quot; height=&quot;110&quot;  src=&quot;http://blog.preinheimer.com/uploads/Lytro-TTR-Cards.serendipityThumb.jpg&quot;  alt=&quot;&quot; /&gt;&lt;/a&gt;&amp;#160;&lt;a class=&quot;serendipity_image_link&quot;  href=&#039;http://blog.preinheimer.com/uploads/Lytro-TTR-Trains.jpg&#039;&gt;&lt;!-- s9ymdb:36 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;110&quot; height=&quot;110&quot;  src=&quot;http://blog.preinheimer.com/uploads/Lytro-TTR-Trains.serendipityThumb.jpg&quot;  alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;br style=&quot;clear: both;&quot;/&gt;

&lt;p&gt;As you&#039;ve noticed, the two images are focused at different depths. The cards are in focus in the first image, while the trains on the board are focused in the second. The interesting point is that I only took one picture. I selected which point to focus on after the image was taken, either in camera (via a touch screen), or via their software. You can even &lt;a href=&quot;https://pictures.lytro.com/preinheimer/pictures/86258&quot;&gt;change the focal point yourself&lt;/a&gt; in that image via their website. I find the effect works really well in the short to medium range, switching between two distant objects doesn&#039;t affect much, as we&#039;d expect with such a small lens. &lt;/p&gt;

&lt;h3&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It&#039;s nice to be able to play around with images after the fact
&lt;li&gt;It&#039;s a fun form factor for a camera, easy to fit in a bag
&lt;li&gt;It&#039;s light
&lt;li&gt;It&#039;s cheap in camera terms
&lt;/ul&gt;
&lt;h3&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;I&#039;m not impressed with the &lt;a href=&quot;https://pictures.lytro.com/preinheimer/pictures/41885&quot;&gt;Colour Performance&lt;/a&gt;, even with lots of light&lt;/li&gt;
&lt;li&gt;The lens cap is useless, it sticks on magnetically, but falls off with even a glancing touch&lt;/li&gt;
&lt;li&gt;Exported image quality isn&#039;t great&lt;/li&gt;
&lt;li&gt;Lytro software isn&#039;t that powerful, I need to export to jpg before I can do any real work&lt;/li&gt;
&lt;li&gt;LCD Screen has rather low resolution. Apple went Retina, Lytro went the other direction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Comparison Shots&lt;/h3&gt;
&lt;p&gt;I tried to take basically the same picture of flowers with my iPhone 4, Lytro, and Nikon D80 (which sells for around &lt;a href=&quot;http://www.ebay.com/itm/Nikon-D80-10-2MP-Digital-SLR-Camera-Kit-with-18-135mm-AF-S-DX-Zoom-Nikkor-Lens-/110856765756?pt=Digital_Cameras&amp;hash=item19cf94013c#ht_826wt_1141&quot;&gt;$400 on eBay&lt;/a&gt;).&lt;br /&gt;
&lt;a class=&quot;serendipity_image_link&quot;  href=&#039;http://blog.preinheimer.com/uploads/iPhone-Flowers.jpg&#039;&gt;&lt;!-- s9ymdb:38 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;110&quot; height=&quot;110&quot;  src=&quot;http://blog.preinheimer.com/uploads/iPhone-Flowers.serendipityThumb.jpg&quot;  alt=&quot;&quot; /&gt;&lt;/a&gt;&amp;#160;&lt;a class=&quot;serendipity_image_link&quot;  href=&#039;http://blog.preinheimer.com/uploads/Lytro-Flowers.jpg&#039;&gt;&lt;!-- s9ymdb:39 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;110&quot; height=&quot;110&quot;  src=&quot;http://blog.preinheimer.com/uploads/Lytro-Flowers.serendipityThumb.jpg&quot;  alt=&quot;&quot; /&gt;&lt;/a&gt;&amp;#160;&lt;a class=&quot;serendipity_image_link&quot;  href=&#039;http://blog.preinheimer.com/uploads/D80-Flowers.jpg&#039;&gt;&lt;!-- s9ymdb:37 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;110&quot; height=&quot;110&quot;  src=&quot;http://blog.preinheimer.com/uploads/D80-Flowers.serendipityThumb.jpg&quot;  alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;br style=&quot;clear: both;&quot;/&gt;
iPhone photo was taken on an iPhone 4, pulled off the camera with iPhoto, cropped and resized down to 1024x1024 in Photoshop, then exported using 81% jpeg. Lytro was imported using their software, the focal point was set to the flower, and it was exported at the only available resolution. D80 Photo was pulled off the card with Lightroom, cropped and white balanced in Lightroom, then exported.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Overall, I&#039;d say it&#039;s a fun gimmick, very much a &quot;point and shoot&quot; camera. It&#039;s a fun thing to throw in the bag to play with, but I generally know where my focal point is when I&#039;m shooting. I can&#039;t think of a time that I wanted to change it after the fact. I have been in situations where I wish I could have focused better after the fact, but generally there I&#039;m dealing with items that are far enough away that the Lytro wouldn&#039;t matter. They&#039;re pretty cheap (by photography standards), and the technology will only get better. &lt;/p&gt; 
    </content:encoded>

    <pubDate>Sun, 08 Apr 2012 20:47:00 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/380-guid.html</guid>
    
</item>
<item>
    <title>Improving Query Performance</title>
    <link>http://blog.preinheimer.com/index.php?/archives/379-Improving-Query-Performance.html</link>
            <category>PHP</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/379-Improving-Query-Performance.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=379</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=379</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;Some aspects of &lt;a href=&quot;https://load.wondernetwork.com/&quot;&gt;Natural Load Testing&lt;/a&gt;&#039;s site have never really performed that well. The site was under incredibly rapid development so I didn&#039;t want to invest too much time in making performance tweaks on code or even architecture that might change in the next week.&lt;/p&gt;
     
&lt;blockquote&gt;No joke, we&#039;ve re-written our load tester at least three times. Two complete re-writes in the same language, then we switched languages to get better threading performance&lt;/blockquote&gt;

&lt;p&gt;I think we hit some sort of limit in the past week or two, and things got &lt;span style=&quot;font-weight: 700;&quot;&gt;much&lt;/span&gt; worse. Pages that used to be snappy jumped up to taking 10 seconds to load. Clearly something needed to be done.&lt;/p&gt;

&lt;p&gt;When our load tester runs, we generate a run id, here&#039;s an example: &lt;span class=&quot;code-inline&quot;&gt;21_20111116_4ec4802b9e7b8_000016&lt;/span&gt;. That&#039;s the user id of whomever launched the test, the date, a unique identifier, and the id of the spawned worker. I wanted something unique, and easy to track if anything went wrong, and that certainly fit the bill. &lt;/p&gt;

&lt;p&gt;Unfortunately it also left me executing plenty of queries along the lines of:
&lt;span class=&quot;code&quot;&gt;SELECT
    min(`test_results`.`timestamp`)AS `min`,
    max(`test_results`.`timestamp`)AS `max`,
    sum(`test_results`.`response_time`) / 1000 AS `diff`,
    count(`test_results`.`run_id`)AS `completed_requests`,
    `test_results`.`run_id`,
    sum(`response_size`) as `total_transferred`,
    max(`test_results`.`response_time`) AS `longest`
  FROM
    `test_results`
  WHERE
    `test_results`.`run_id` LIKE(&#039;21_20111116_4ec4802b9e7b8_%&#039;)
  GROUP BY
    `test_results`.`run_id`
  ORDER BY
    `test_results`.`run_id` ASC
&lt;/span&gt;

one key problem there is the &lt;span class=&quot;code-inline&quot;&gt;WHERE `test_results`.`run_id` LIKE(&#039;21_20111116_4ec4802b9e7b8_%&#039;)&lt;/span&gt;. Even indexed, that query has a hard time. I tried a few optimization techniques with different index types or other options, but the query was still hurting.&lt;/p&gt;

&lt;p&gt;The solution was to break up that run_id into its components: the run id, and the worker id. This wasn&#039;t quite as pain free as it could have been (user IDs with different lengths forced me to go through this in several iterations) but I&#039;m quite happy with the results. MySQL is performing a HASH index on the new run_id column, which seems perfect for this situation (there&#039;s no web interface to do anything other than an exact lookup on that column). &lt;/p&gt;

&lt;h3&gt;Results&lt;/h3&gt;
&lt;p&gt;
&lt;b&gt;Before&lt;/b&gt;: &lt;span class=&quot;code-inline&quot;&gt;10 rows in set (11.49 sec)&lt;/span&gt; &lt;br /&gt;
&lt;b&gt;After&lt;/b&gt;: &lt;span class=&quot;code-inline&quot;&gt;10 rows in set (0.00 sec)&lt;/span&gt;&lt;br /&gt;

Sometimes you need to look further than simple indexes and query optimizations to solve problems. &lt;/p&gt; 
    </content:encoded>

    <pubDate>Fri, 23 Mar 2012 21:29:41 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/379-guid.html</guid>
    
</item>
<item>
    <title>Wish: Cyclists who follow the rules</title>
    <link>http://blog.preinheimer.com/index.php?/archives/378-Wish-Cyclists-who-follow-the-rules.html</link>
            <category>Wednesday Wishes</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/378-Wish-Cyclists-who-follow-the-rules.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=378</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=378</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    I love cycling, I managed to log 1400km on my bike in 2010 and I&amp;#8217;d like to beat that this summer.&lt;br /&gt;
&lt;br /&gt;
The thing I hate most about cycling: Other cyclists.&lt;br /&gt;
&lt;br /&gt;
Cars treat cyclists like crap, and as an aggregate we deserve it. Cyclists routinely run red lights weaving through pedestrians and cars as they cross the street, run stop signs cutting off cars that have begun to cross, ride the wrong way down one way streets, take to sidewalks when the road is slow, cut in front of turning vehicles while continuing forwards, etc. etc.&lt;br /&gt;
&lt;br /&gt;
I wish more cyclists behaved, so we could start expecting cars to treat us fairly.&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Wed, 21 Mar 2012 20:35:42 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/378-guid.html</guid>
    
</item>
<item>
    <title>Loop Me</title>
    <link>http://blog.preinheimer.com/index.php?/archives/377-Loop-Me.html</link>
            <category>Wednesday Wishes</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/377-Loop-Me.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=377</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=377</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;As fine patrons of the Internet we&amp;#8217;re bombarded daily with brief, one-sided snippets of news at a terrifying rate. News aggregation sites like Fark, Hacker News, and Reddit can further exacerbate the issue with even more sensational (or funny) headlines, and calls to action. Stories can &amp;#8220;go viral&amp;#8221; long before the other party knows what&amp;#8217;s happening, let alone mount a convincing defence. Secondary updates or retractions rarely receive the prominence of the original article. &lt;/p&gt;

&lt;p&gt;What I&amp;#8217;d like to see is an easy way to ask to be &amp;#8220;brought into the loop&amp;#8221; on future updates to a story. When someone feels outraged, or surprised by an article they&amp;#8217;d be able click a button, and future updates (possibly weeks or months later) would be pushed to them via email or standard aggregation systems. Ideally, this would be a third party service, provided like the social buttons we see on sites now (Like, +1, Tweet, Stumble, Trip, Fall, etc.), which would curate the links between stories. They&amp;#8217;d understand how many sites re-hash the same wire stories in the present, and be able to link those as related stories to what was issued in the past. This way when we&amp;#8217;re &amp;#8220;Looped&amp;#8221; in we&amp;#8217;d be able to see the full series of articles in chronological order, and updates could effectively root out long standing (and now unwarranted) misconceptions. &lt;/p&gt;

&lt;p&gt;As an example: I read an article on Saturday where a &lt;a href=&quot;http://www.cnn.com/2012/03/10/us/minnesota-student-privacy/index.html&quot;&gt;girl alleges that she was forced to give up her facebook &amp;#38; email password to school administrators while basically being interrogated at school&lt;/a&gt;. A lawsuit is at play, so it&amp;#8217;s unlikely I&amp;#8217;ll hear the full story until it&amp;#8217;s played out in a court case. At present, I&amp;#8217;m astounded and disappointed in the school, though it&amp;#8217;s entirely possible in the end I&amp;#8217;ll simply feel deceived by a sixth-grader. At this point, it&amp;#8217;s unlikely I&amp;#8217;ll ever hear the end of this story; boring updates to yesterday&amp;#8217;s sensationalism rarely receive comparable coverage, even in today&amp;#8217;s 24 hour news cycle, and I feel that does a disservice to everyone. &lt;/p&gt;


&lt;p&gt;With this, I think we&amp;#8217;d have a populace informed not only by &lt;a href=&quot;http://www.webcitation.org/query?url=http%3A%2F%2Fwww.thestar.com%2Fnews%2Fworld%2Farticle%2F668284&amp;#38;date=2009-08-07&quot;&gt;sensational allegations&lt;/a&gt;, but grounded by an &lt;a href=&quot;http://www.webcitation.org/query?url=http%3A%2F%2Fwww.signonsandiego.com%2Fnews%2F2009%2Fsep%2F30%2Fus-fact-check-obama-opponents-093009%2F&amp;#38;date=2010-08-20
&quot;&gt;eventual truth&lt;/a&gt;.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Wed, 14 Mar 2012 13:21:00 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/377-guid.html</guid>
    
</item>
<item>
    <title>User Feedback, the endless cycle</title>
    <link>http://blog.preinheimer.com/index.php?/archives/376-User-Feedback,-the-endless-cycle.html</link>
            <category>Op-Ed</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/376-User-Feedback,-the-endless-cycle.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=376</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=376</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;We spent several months on &lt;a href=&quot;https://load.wondernetwork.com/beta/&quot;&gt;Natural Load Testing&lt;/a&gt; before launch, we also spent a considerable portion of the cash reserve &lt;a href=&quot;https://wonderproxy.com&quot;&gt;WonderProxy&lt;/a&gt; had built up on smart people to help us along. We felt&amp;#8230; pretty awesome. We started expanding our beta a bit further, and the feedback started rolling in. Key Feedback like: &amp;#8220;It doesn&amp;#8217;t work&amp;#8221;, and &amp;#8220;Something is broken&amp;#8221; as well as silent feedback, where users got to a certain point in the process then stopped using the service entirely. That was&amp;#8230; not so awesome.&lt;/p&gt;

&lt;p&gt;The problem users ran into was quite understandable: A lack of ajax on our load testing page required users to manually refresh the page for results to appear. A quick glance at my wall calendar confirms that it&amp;#8217;s no longer 2006, and this is an entirely reasonable position for our users to take.&lt;/p&gt;

&lt;p&gt;I sat down, and started resolving the feedback as quickly as I could. My list of changes currently looks something like this:
&lt;ul&gt;
&lt;li&gt;****Ajax updates on Run and Calibration pages (&amp;#8220;it doesn&amp;#8217;t work&amp;#8221;)**** DONE &lt;/li&gt;
&lt;li&gt;Better navigation, you have to go home after every step IN PROGRESS&lt;/li&gt;
&lt;li&gt;Delete things, Suites, etc.     DONE&lt;/li&gt;
&lt;li&gt;*Graph results in real time*&lt;/li&gt;
&lt;li&gt;Estimated Time to Completion for test running page&lt;/li&gt;
&lt;li&gt;Configure threshold for reporting rows (currently hardcoded at 1000ms+) DONE&lt;/li&gt;
&lt;li&gt;Newer tests at the top of the run page DONE&lt;/li&gt;
&lt;li&gt;Plot tests to compare runs&lt;/li&gt;
&lt;li&gt;Fancy &amp;#8220;load server&amp;#8221; feature&lt;/li&gt;
&lt;li&gt;Deep Copy Suites DONE &lt;/li&gt;
&lt;li&gt;Change Suite Domain DONE &lt;/li&gt;
&lt;li&gt;Better identify the calibration runs on test suites DONE &lt;/li&gt;
&lt;li&gt;Check Time Elapsed column ms vs seconds DONE &lt;/li&gt;
&lt;li&gt;Name Runs DONE&lt;/li&gt;
&lt;li&gt;Add min width on response time&lt;/li&gt;
&lt;li&gt;allow editing test suites&lt;/li&gt;
&lt;li&gt;Calibration run can&amp;#8217;t actually compare to anything DONE&lt;/li&gt;
&lt;li&gt;left align suite name (and make this a link) DONE&lt;/li&gt;
&lt;li&gt;make start time not a link DONE&lt;/li&gt;
&lt;li&gt;make editing run title only happen when you click the pencil&lt;/li&gt;
&lt;li&gt;zebra stripes for result tables! DONE &lt;/li&gt;
&lt;li&gt;Timings aren&amp;#8217;t being saved in configure  DONE &lt;/li&gt;
&lt;li&gt;Rename Tests (not just suites)&lt;/li&gt;
&lt;li&gt;Change domains on a Test level (not just test suite)&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;My original plan was to fix a few critical items that led to users thinking things were broken, then work on the beta invite list. As I finished each item, I looked at the list (which originally only contained a few items) and decided I needed to finish a few more before I could invite users.&lt;/p&gt;

&lt;p&gt;It took me a few weeks to discover I was in an endless cycle. Users will always have feedback on how your site could be better. If I kept going like this, a year from now I&amp;#8217;d have an incredibly polished site, with two users.&lt;/p&gt;

&lt;p&gt;So, I broke the cycle. I just sent out another batch of invites, and I feel great.&lt;br /&gt;
&lt;span style=&quot;font-size: small; font-style: italic;&quot;&gt;but not that great about the typo in the From field of that email &lt;img src=&quot;http://blog.preinheimer.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 13 Mar 2012 22:35:10 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/376-guid.html</guid>
    
</item>
<item>
    <title>No Google Ads on Ping Data</title>
    <link>http://blog.preinheimer.com/index.php?/archives/375-No-Google-Ads-on-Ping-Data.html</link>
            <category>Op-Ed</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/375-No-Google-Ads-on-Ping-Data.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=375</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=375</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    While Will and I were working on the &lt;a href=&quot;https://wondernetwork.com/pings/&quot;&gt;Global Ping Data&lt;/a&gt; pages, I briefly considered putting Google Ads on those pages, to try and get some revenue from the traffic we&#039;re expecting. I quickly shot that down.&lt;br /&gt;
&lt;br /&gt;
I think ads make sense for sites that generate or syndicate content as their only purpose. Sites like &lt;a href=&quot;http://arstechnica.com&quot;&gt;Ars Technica&lt;/a&gt; or &lt;a href=&quot;http://slashdot.org&quot;&gt;Slashdot&lt;/a&gt; or even my friend &lt;a href=&quot;http://shiflett.org/&quot;&gt;Chris Shiflett&#039;s blog&lt;/a&gt; all fit that bill. That, however, is not what we&#039;re trying to do with this data. Our goal instead is to raise product and brand awareness for &lt;a href=&quot;https://wonderproxy.com/&quot;&gt;WonderProxy&lt;/a&gt;, &lt;a href=&quot;http://wheresitup.com&quot;&gt;Where&#039;s It Up?&lt;/a&gt; and &lt;a href=&quot;http://load.wondernetwork.com&quot;&gt;Natural Load Testing&lt;/a&gt;. Adding advertisements to these pages would only distract from our goals, so while there may be some short term revenue gain, I think they&#039;d end up costing us more in the long term.&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Mon, 06 Feb 2012 13:03:00 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/375-guid.html</guid>
    
</item>
<item>
    <title>Cookies don't replace Sessions</title>
    <link>http://blog.preinheimer.com/index.php?/archives/373-Cookies-dont-replace-Sessions.html</link>
            <category>PHP</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/373-Cookies-dont-replace-Sessions.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=373</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=373</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;I&amp;#8217;ve seen several instances where people have demonstrated the ease with which encrypted cookies can replace sessions within PHP. &lt;a herf=&quot;http://nitschinger.at/&quot;&gt;Michael Nitschinger&lt;/a&gt; wrote &lt;a href=&quot;http://nitschinger.at/Session-Encryption-with-Lithium&quot;&gt;a piece&lt;/a&gt; recently demonstrating the switch with Lithium, while CodeIgniter does this &lt;a href=&quot;http://codeigniter.com/user_guide/libraries/sessions.html&quot;&gt;by default&lt;/a&gt; (optionally encrypting). The problem is that while replacing sessions with cookies works, it introduces a few risks not present with native session support, and these risks tend to be under documented. &lt;/p&gt;

&lt;p&gt;Encryption is often viewed as a panacea for security problems, you sprinkle a little encryption dust around, and your problems dissolve. Unfortunately, while properly implemented encryption solves the problem of other people reading your encrypted data quite well, it doesn&amp;#8217;t do much else. It doesn&amp;#8217;t (on its own) tell you if other people have duplicated your data, manipulated the data in question, or handed you an old copy of properly encrypted data. &lt;/p&gt;

&lt;p&gt;Consider an attacker who manages to sit in between Amazon and one of their warehouses. Amazon (in this theoretical example) encrypts all order instructions well, then transmits them to the warehouse. The warehouse decrypts the instruction, fills the order, and ships. If the attacker wanted free stuff they could place an order during a low traffic period, and wait for Amazon to send an encrypted message and make a copy. A few minutes later they could re-send that encrypted message to the warehouse, never having even tried to read it. With luck, they&amp;#8217;ll soon receive two of whatever they just ordered! This is an instance of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Replay_attack&quot;&gt;replay attack&lt;/a&gt;, and that vulnerability is the one this post will examine in detail. &lt;/p&gt;


&lt;h3&gt;Exploiting cookie based sessions&lt;/h3&gt;
&lt;p&gt;Executing a replay attack against a cookie based session is easy, legitimately obtain some desired state on the system in question, and make a copy of your cookies. Should something go wrong, simply restore your cookies to the previous state. To demonstrate this, I&amp;#8217;ve created a sample gambling application, you can get the &lt;a href=&quot;https://github.com/preinheimer/Betting-Example&quot;&gt;source from github&lt;/a&gt;, or &lt;a href=&quot;http://betting-example.orchestra.io/&quot;&gt;Play Now&lt;/a&gt;! (thanks to &lt;a href=&quot;http://www.engineyard.com/products/orchestra&quot;&gt;Orchestra.io&lt;/a&gt;, it&#039;s a free account so give it a moment)&lt;/p&gt;

&lt;p&gt;In the game you start with $1000, then have the ability to make arbitrary wagers. Make a few bets to get a feel for the system, then make a copy of your cookie values. Bet again. If you lose money, simply restore your earlier cookies to get that money back. That&amp;#8217;s it. This attack works because the system is willing to accept any successfully decrypted message as a valid, and current, session. &lt;/p&gt;

&lt;p&gt;This attack doesn&amp;#8217;t exist under traditional session storage. The user&amp;#8217;s cookie doesn&amp;#8217;t change from one request to the next as their money goes up and down. If a system is regenerating the session ID when the user changes privilege levels, the old session is deleted and no longer available when invoked properly:

&lt;span class=&quot;code&quot;&gt;session_regenerate_id(TRUE);&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;A system using cookie based session storage, while using a &lt;a href=&quot;http://en.wikipedia.org/wiki/Captcha&quot;&gt;CAPTCHA&lt;/a&gt; to defeat bots is doomed to fail, the attacker could solve the CAPTCHA once, then re-use that same cookie a million times. Encryption makes it difficult for an attacker to read the message, additional systems must be bolted on to defend against this sort of attack. In the stateless world of HTTP and the web, this is exceedingly difficult without some server-side datastore.&lt;/p&gt;

&lt;p&gt;While this was clearly a trivial example, the problem is not. If you&amp;#8217;re looking at using cookie based sessions it&amp;#8217;s one of the things you need to be aware of.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re interested in learning more about cryptography, including a great rundown of this problem and many others, I&amp;#8217;d highly recommend &lt;a href=&quot;http://www.amazon.com/gp/product/0471223573/ref=as_li_ss_tl?ie=UTF8&amp;#38;tag=preinheimerco-20&amp;#38;linkCode=as2&amp;#38;camp=1789&amp;#38;creative=390957&amp;#38;creativeASIN=0471223573&quot;&gt;Practical Cryptography&lt;/a&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Mon, 23 Jan 2012 12:48:00 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/373-guid.html</guid>
    
</item>
<item>
    <title>Colours of Light</title>
    <link>http://blog.preinheimer.com/index.php?/archives/374-Colours-of-Light.html</link>
            <category>Op-Ed</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/374-Colours-of-Light.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=374</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=374</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;Take a look at this picture I took in the mall, in particular the Reitmans, Stokes, and Carleton Cards stores (left to right accordingly): &lt;a class=&quot;serendipity_image_link&quot;  href=&#039;http://blog.preinheimer.com/uploads/mall_light_large.jpg&#039;&gt;&lt;!-- s9ymdb:33 --&gt;&lt;img class=&quot;serendipity_image_left&quot; width=&quot;356&quot; height=&quot;200&quot;  src=&quot;http://blog.preinheimer.com/uploads/mall_light_small.jpg&quot;  alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;The stores look very different, mostly due to the colour of light they&#039;ve used. In the Carleton Cards, there&#039;s a yellow light, adding a bit of warmth to a store built around relationships and expressing feelings. Stokes (a kitchen store) uses a very clean, white light, appropriate for clean kitchens, and pushing that meme. Reitmans (a clothing store) uses a rose coloured light which improves the look of skin for most people (especially us pasty Caucasians in the middle of winter). &lt;/p&gt;

&lt;p&gt;Just another way stores are marketing to you that&#039;s easy to miss. &lt;/p&gt;

 
    </content:encoded>

    <pubDate>Sat, 21 Jan 2012 22:41:17 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/374-guid.html</guid>
    
</item>
<item>
    <title>An end to if statements presented by Computers</title>
    <link>http://blog.preinheimer.com/index.php?/archives/372-An-end-to-if-statements-presented-by-Computers.html</link>
            <category>Wednesday Wishes</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/372-An-end-to-if-statements-presented-by-Computers.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=372</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=372</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    I get quite a bit of email, and deal with quite a few automated systems, banks, credit card companies, the cable company, etc. I&amp;#8217;m tired of automated systems forcing me to ask myself a question to figure out what&amp;#8217;s happening.&lt;br /&gt;
&lt;br /&gt;
Here&amp;#8217;s the first email I found with the word &amp;#8220;if&amp;#8221; in it:&lt;br /&gt;
&lt;blockquote&gt;We wanted to let you know that your order has shipped. If you ordered multiple items, you may receive separate shipments with no additional shipping charges.&lt;/blockquote&gt;&lt;br /&gt;
My problem is that the email contains an &amp;#8220;if&amp;#8221;. There&amp;#8217;s no reason for it. The computer that sent the email either does have access, or should have access, to my order. It knows that I only ordered a single product, so there&amp;#8217;s no point in wasting my time with any other information.&lt;br /&gt;
&lt;br /&gt;
My bank does something even more confusing:&lt;br /&gt;
&lt;blockquote&gt;A fee of $1.50 will be charged in the currency of the account for each cheque viewed. The fee will be debited from your account by the next business day. You may view a cheque as many times as you wish during your current EasyWeb session.&lt;br /&gt;
For personal chequing accounts the View Cheque service is free for customers who havePaperless or Online Only record keeping. &lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
I have no idea what kind of account type I have. I push &amp;#8220;Checking&amp;#8221; to get money out of the ATM, but that doesn&amp;#8217;t seem to be what it&amp;#8217;s asking for. I opened this account when I was 16 years old, at a branch and bank that no longer exists. Do I have &amp;#8220;Paperless&amp;#8221; or &amp;#8220;Online Only&amp;#8221; record keeping? I&amp;#8217;m not sure. Not knowing may cost me $1.50, but the computer running the bank most certainly knows what options I have on my account. That&amp;#8217;s how it will know to charge me if I&amp;#8217;ve got the wrong kind of account. Yet, I&amp;#8217;m faced with the question.&lt;br /&gt;
&lt;br /&gt;
Seeing these issues reminds me of an article I read back in 2004: &lt;a href=&quot;http://www.asktog.com/Bughouse/10MostWantedDesignBugs.html &quot;&gt;Ten most persistent design bugs&lt;/a&gt; in particular &amp;#8220;let you save me some time.&amp;#8221;&lt;br /&gt;
&lt;br /&gt;
In both these cases the developer decided to let me save him or her some time. They didn&amp;#8217;t complicate their page or email template with an if structure, and instead presented one to me. Every Single person who interacts with that page, or gets that email is now forced to determine which case applies to them, all an effort to save some work on the part of one developer/designer some time ago.&lt;br /&gt;
&lt;br /&gt;
It&amp;#8217;s a stupid waste, and I wish it would stop. 
    </content:encoded>

    <pubDate>Wed, 18 Jan 2012 10:08:35 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/372-guid.html</guid>
    
</item>
<item>
    <title>Persistent Person Tags</title>
    <link>http://blog.preinheimer.com/index.php?/archives/371-Persistent-Person-Tags.html</link>
            <category>Wednesday Wishes</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/371-Persistent-Person-Tags.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=371</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=371</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;I wish it was easy for me to persistently and privately tag an individual on the Internet with a keyword, then hopefully a short justification. When reading an interesting blog post or tweet you could tag them as interesting or understands cryptography or the like. Then the next time you ran into a post, comment, tweet, conference schedule, whatever from that individual that tag would be visible. &lt;/p&gt;

&lt;p&gt;It could in theory live almost entirely in the browser, but I think it would work best with some sort of centralized backend to facilitate cross device consistency. &lt;/p&gt;

&lt;p&gt;It doesn&amp;#8217;t need to be perfect, nor does it need to pierce any sort of attempt at anonymity. Think about &lt;a href=&quot;http://en.gravatar.com/&quot;&gt;gravatar&lt;/a&gt;, a great service that plugs your picture into blog comments through your email address. It&amp;#8217;s neither perfect nor completely pervasive but it&amp;#8217;s still helpful.&lt;/p&gt;

&lt;p&gt;To be clear this isn&amp;#8217;t something I want to add onto Facebook or Twitter. I&amp;#8217;m not friends with these people, I don&amp;#8217;t need to hear when they&amp;#8217;re drunk, dating, or farming pixels. Nor do I want to read every inane comment or checkin they push to Twitter. I&amp;#8217;d simply like a little icon to appear the next time I encounter them on any medium letting me know they&amp;#8217;re brilliant, or a racist bigot so I can react appropriately&amp;#8230;&lt;/p&gt;

&lt;p&gt;Apart from the (hopefully) apparent utility, I also think this helps bring us back something we&amp;#8217;ve lost. One hundred years ago if someone said something interesting to you they were standing in front of you (or at least within earshot) and you&amp;#8217;d likely have an easy time remembering that individual to credit them later, or simply pay extra attention that individual attempted to share a remark. By the same token if someone said something idiotic and offensive you&amp;#8217;d have an easy time remembering them, and simply walk to the other side of the bar when they mount their soap box. We&amp;#8217;re exposed to opinions from nearly faceless individuals at a terrifying rate these days, and along the way lost the ability to appropriately credit the things we&amp;#8217;ve seen, this wish would make serious progress to fix that.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Wed, 11 Jan 2012 23:16:56 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/371-guid.html</guid>
    
</item>
<item>
    <title>The Danger of Hooks</title>
    <link>http://blog.preinheimer.com/index.php?/archives/370-The-Danger-of-Hooks.html</link>
            <category>PHP</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/370-The-Danger-of-Hooks.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=370</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=370</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;i&gt;I fell in love with Hooks in frameworks recently; the honeymoon period was tragically short.&lt;/i&gt;

&lt;h3&gt;First, the love story:&lt;/h3&gt;
&lt;p&gt;I ran into hooks rather simultaneously with two very different frameworks: Code Igniter and Lithium. In both cases I was using a rather nifty hook to handle ensuring that users were properly authenticated and authorized before accessing a page. I think we can all agree having to add some code to every single method is foolhardy:
&lt;span class=&quot;code&quot;&gt;if (!isset($_SESSION[&#039;user_level&#039;]) OR ($_SESSION[&#039;user_level&#039;] != &#039;admin&#039;))
{
     header(&#039;Location: &#039; . APP_ROOT_URI);
     exit;
}
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Hooks provide a great way to solve the issue. Within Lithium you can leverage the filters mechanism to handle authentication quite easily, in fact it&#039;s an &lt;a href=&quot;http://dev.lithify.me/drafts/source/en/02_lithium_basics/02_filters.wiki&quot;&gt;example case&lt;/a&gt; in their tutorials. The beautiful thing about it in my mind is the simplicity of things at the controller level: I simply list the publicly accessible methods in a property (public $publicActions = array(&#039;login&#039;);), and everything else is assumed to only be accessible to logged in users. Fantastic! If I mess up when adding a new method, it defaults to closed, which is exactly the result I&#039;m looking for. &lt;/p&gt;

&lt;p&gt;Over with Code Igniter things are really quite similar. The &lt;a href=&quot;http://codeigniter.com/user_guide/general/hooks.html&quot;&gt;post_controller_constructor&lt;/a&gt; hook can be used to invoke a specific class and controller. That class can return true, redirect a user, whatever as appropriate. Since it&#039;s invoked after the controller is instantiated, similar configuration options can be made available.&lt;/p&gt;

&lt;h3&gt;The honeymoon&lt;/h3&gt;
&lt;p&gt;I ripped redundant, error prone, easy to forget, and fundamentally stupid checks out of all of the controllers where I&#039;d added them. These new systems were much easier to maintain, required a lot less code, and I didn&#039;t need to add 10 lines of unrelated bloat into each controller. Life was grand. Days where I wrote negative lines of code felt glorious.&lt;/p&gt;

&lt;h3&gt;The big fight&lt;/h3&gt;
&lt;p&gt;One day, while messing around, I accidentally turned off the hook configuration within Code Igniter (actually I clobbered a file, and restored the wrong one). Then, things came crashing down in a horrible cacophony of... actually they didn&#039;t. Everything kept working: that was the problem. The entirety of my security system was turned off because one file was wrong, and things kept working. Sure, specific calls that referenced the current user&#039;s username broke, but there was more than enough left vulnerable for me to get a big chill.&lt;/p&gt;

&lt;h3&gt;Counselling&lt;/h3&gt;
Revisiting the hooks system, I was shocked by the tremendous lack of depth in my defense: one mis-configured file and security was off. Even worse, nothing broke. There was no evidence that the security was disabled unless you went probing, which is horrible. The only thing worse than a safe that won&#039;t lock, is one that looks like it&#039;s locked but pulls open to a slight touch.

&lt;h3&gt;Conciliation&lt;/h3&gt;
The easy thing to reach for with both Lithium, and Code Igniter is __construct(). A single, unified location to ensure that the authorization tests have been executed. Unfortunately, in both cases __construct() is called long before the authorization hooks are run. More specialized solutions are required. 

&lt;h3&gt;With Lithium&lt;/h3&gt;
&lt;p&gt;The __invoke() method is invoked after the authorization filter, so it&#039;s a great candidate for double checking. 
&lt;span class=&quot;code&quot;&gt;    public function __invoke($request, $dispatchParams, array $options = array()) {
          if (!defined(&#039;AUTH_CHECKED&#039;))
          {
               throw new DispatchException(&#039;Authorization filter not run.&#039;);
          }
          return parent::__invoke($request, $dispatchParams, $options);
     }
&lt;/span&gt;&lt;/p&gt;


&lt;h3&gt;With Code Igniter&lt;/h3&gt;
&lt;p&gt;The _remap() function is called (when available) to allow you to remap incoming requests to a different method. Since it&#039;s invoked universally, the check can go there.
&lt;span class=&quot;code&quot;&gt;    public function _remap($method)
    {
        if(defined(&#039;AUTH_CHECKED&#039;))
        {
            $this-&gt;$method();    
        }else {
            exit(&#039;ACL Configuration Error&#039;);
        }
    }
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Both of these cases provided me with the depth I was looking for. I&#039;m no longer entirely dependent on one configuration option or file for my security to function. Should it fail, I&#039;ve got a secondary check in place; this example of defence in depth allows me to be comfortable with the hooks security system once more.&lt;/p&gt;

&lt;h3&gt;Final thoughts&lt;/h3&gt;
&lt;p&gt;Through researching this, and exploring several code bases to which I have access, I&#039;ve noticed two distinct strategies for managing method level access. In Lithium, each class indicates which methods should be accessible to which security groups using a public property; by contrast, in the other strategy, public methods were explicitly laid out inside the single authorization function. The former has the advantage of allowing you to quickly and easily manage security while you add functions to a given controller; the latter solves the issue of your authorization rules being scattered across each and every controller by centralizing them in one easy to locate file. &lt;/p&gt;
&lt;h3&gt;Updates!&lt;/h3&gt;
&lt;p&gt;Some suggestions have cropped up:
&lt;ul&gt;
&lt;li&gt;Unit Testing&lt;/li&gt;
While I&#039;ll agree that great, properly implemented, unit testing would have caught this it still doesn&#039;t leave me feeling comfortable. First, I&#039;ve seen a lot of unit testing code, and much of it wouldn&#039;t have caught this. Either because the code specifically tested the authentication, and authorization code on its own, not combined with the actual controllers. Or because it used its own configuration file during testing, missing the fact that something had been removed from production. Second, I&#039;m not sure that simply exposing the issue with unit testing would make me comfortable, I definitely would have caught it faster. Possibly even as soon as I&#039;d committed the code. But I&#039;d still like something running along side the code constantly to make sure the checks are in place.
&lt;li&gt;Auth Specific Class&lt;/li&gt;
As suggested by &lt;a href=&quot;https://twitter.com/#!/inxilpro&quot;&gt;Chris Morrell&lt;/a&gt; (in this &lt;a href=&quot;http://www.exquisitetweets.com/tweets?eids=lJ9loCqRgG.lKbHznxQxo.lKcdhv7p3A.lKesxSg81k.lKeWg7XtAa.lKffVp19l6.lKfrX1BN24.lKfw771NF6.lKh9i7Hyfc.lKiN5Umw8a#tweet2&quot;&gt;series of tweets&lt;/a&gt;) I could be using a dedicated &lt;a href=&quot;https://gist.github.com/1590022&quot;&gt;authorization class&lt;/a&gt;. While this does solve the configuration problem by calling it explicitly, I&#039;m losing granularity or making a call with every action. I&#039;ll lose granularity if I decide to put one initial call in my constructor (or other early globally called method) since it affects the entire class. Ending up making a call with every action was exactly what I was trying to avoid in the first place. That said, the use of getIdentity() vs requireIdentity() is quite slick, I like how simultaneously explicit and transparent a normal action becomes. 
&lt;/ul&gt;
&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 10 Jan 2012 09:27:01 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/370-guid.html</guid>
    
</item>
<item>
    <title>DVD Ripper, that Works</title>
    <link>http://blog.preinheimer.com/index.php?/archives/369-DVD-Ripper,-that-Works.html</link>
            <category>Wednesday Wishes</category>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/369-DVD-Ripper,-that-Works.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=369</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=369</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;i&gt;This is the first in a continuing series of things I wish. Posted on Wednesdays&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&quot;This doesn&#039;t sound hard&quot;&lt;br /&gt;
&lt;br /&gt;
All I want is a DVD ripper that can do what a CD ripper did over a decade ago. I&#039;d like to insert a DVD into my computer, have it look up the meta data on some sort of modern &lt;a href=&quot;http://en.wikipedia.org/wiki/CDDB&quot;&gt;CDDB&lt;/a&gt; equivalent, then rip the disk with appropriate meta data for iTunes. It will need to understand the difference between Television and Movies, as well as how to rip the right audio track, and what chapters are associated with what episode. This really doesn&#039;t seem that hard. Yet, I don&#039;t have one. Everything I&#039;ve seen requires me to figure out those associations, or handles meta data poorly.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://thelittleappfactory.com/ripit/&quot;&gt;RipIt&lt;/a&gt;: Is a functional ripping tool, it however doesn&#039;t seem to understand TV disks. I put in Battlestar Galactica Season 1, Disk 2. It ripped it into a single file, that turned out to be something like the middle of episode 3 to the end of episode 4. &lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://handbrake.fr/&quot;&gt;Handbrake&lt;/a&gt;: Another functional ripping tool, it requires me to figure out which chapters are associated with which episodes on a disc. I don&#039;t want to worry about this, put a disc in, wait, take disk out, repeat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I&#039;m on a mac, though if something truly perfect came out for Linux or Windows I&#039;d rip from a VM.&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Wed, 04 Jan 2012 14:38:51 -0500</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/369-guid.html</guid>
    
</item>
<item>
    <title>&lt;span class=&quot;light&quot;&gt;Updating Theme&lt;/span&gt; Please Stand By</title>
    <link>http://blog.preinheimer.com/index.php?/archives/368-span-classlightUpdating-Themespan-Please-Stand-By.html</link>
    
    <comments>http://blog.preinheimer.com/index.php?/archives/368-span-classlightUpdating-Themespan-Please-Stand-By.html#comments</comments>
    <wfw:comment>http://blog.preinheimer.com/wfwcomment.php?cid=368</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.preinheimer.com/rss.php?version=2.0&amp;type=comments&amp;cid=368</wfw:commentRss>
    

    <author>nospam@example.com (Paul Reinheimer)</author>
    <content:encoded>
    &lt;p&gt;&lt;del&gt;I&#039;m updating my theme at present, this may take a moment.&lt;/del&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I&#039;m still not happy, but it&#039;s at least legible now, I&#039;m going to try blogging again as a constant kick in my own ass to fix it further&lt;/p&gt;&lt;br /&gt;
&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Tue, 31 May 2011 21:13:26 -0400</pubDate>
    <guid isPermaLink="false">http://blog.preinheimer.com/index.php?/archives/368-guid.html</guid>
    
</item>

</channel>
</rss>
