<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Straylight Run</title>
	
	<link>http://www.straylightrun.net</link>
	<description>Software, Technology, PHP</description>
	<lastBuildDate>Tue, 29 Sep 2009 15:33:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/straylightrun" type="application/rss+xml" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">straylightrun</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Of (PHP) Sessions, Cookies, and Authentication</title>
		<link>http://www.straylightrun.net/2009/09/29/of-php-sessions-cookies-and-authentication/</link>
		<comments>http://www.straylightrun.net/2009/09/29/of-php-sessions-cookies-and-authentication/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 15:33:08 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[garbage collection]]></category>
		<category><![CDATA[php.ini]]></category>
		<category><![CDATA[sessions]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/?p=248</guid>
		<description><![CDATA[We’ve never had long-lived sessions.  It was never a requirement.  I think we had a “Remember me” checkbox that didn’t work at one point, but we soon removed it.  But suddenly, customer requests started coming in.  They asked, “why do I have to log in every time I use the site?  Why can’t I stay [...]]]></description>
			<content:encoded><![CDATA[<p>We’ve never had long-lived sessions.  It was never a requirement.  I think we had a “Remember me” checkbox that didn’t work at one point, but we soon removed it.  But suddenly, customer requests started coming in.  They asked, “why do I have to log in every time I use the site?  Why can’t I stay logged in forever, like Facebook or Twitter?”  That was a good question.</p>
<p><span style="text-decoration: underline;"><strong>Basic User Login</strong></span></p>
<p>Like most sites, we used the PHP session to maintain a logged in user for our site.   We started a session, kept track of some data indicating if the user is logged in or not, and that was about it.</p>
<p>I never looked at sessions and cookies in-depth before.  I knew generally how sessions worked.  PHP sets a cookie in the client’s browser.  The cookie contains a session ID.  When a request comes in, PHP reads the session ID, looks for a file corresponding to the ID on disk (or in a database, memcached, etc.), reads in the file containing the session data, and loads the session into the request.  When the request finishes, the session data is saved to the file again.</p>
<p><span style="text-decoration: underline;"><strong>Implementing The “Remember Me” Checkbox</strong></span></p>
<p>First, naively, I thought all I had to do was find the right <a href="http://us3.php.net/manual/en/ini.list.php">php.ini </a>directive to make sessions last forever.  Browsing the PHP manual and googling, I came across the <a href="http://us3.php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime"><code>session.cookie_lifetime</code></a> directive, configured in either php.ini or by <a href="http://us3.php.net/manual/en/function.session-set-cookie-params.php"><code>session_set_cookie_params()</code></a>.</p>
<blockquote><p><em>session.cookie_lifetime</em> specifies the lifetime of the cookie in seconds which is sent to the browser. The value 0 means &#8220;until the browser is closed.&#8221; Defaults to <em>0</em>.</p></blockquote>
<p>I set this to 24 hours.  Well, that was easy, I thought.</p>
<p>Except it didn’t work.  Users reported logging in, going out to lunch, coming back, and getting logged out on the first link clicked.  I dug deeper and found another directive.</p>
<blockquote><p><em><a href="http://us3.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime">session.gc_maxlifetime</a></em> specifies the number of seconds after which data will be seen as &#8216;garbage&#8217; and cleaned up. Garbage collection occurs during session start.</p></blockquote>
<p>It defaults to 1440 seconds, or 24 mins.</p>
<p>It’s important to know that <code>session.cookie_lifetime </code>starts when the cookie is set, regardless of last user activity, so it is an absolute expiration time.  <code>session.gc_maxlifetime </code>starts from <em>when the user was last active (clicked)</em>, so it’s more like a maximum idle time.</p>
<p><span style="text-decoration: underline;"><strong>Starting To Understand</strong></span></p>
<p>Now I could see that both of these directives must cooperate to get the desired effect. Specifically, the shorter of these two values determines my session duration.</p>
<p>For example, let’s say I have <code>session.cookie_lifetime </code>set to its default of 0, and <code>session.gc_maxlifetime </code>is set to its default of 24 mins.  A user who logs in can stay logged in forever, provided he never closes his browser, and he never stops clicking for more than 24 mins.</p>
<p>Now, let’s say the same user takes a 30 min. lunch break, and leaves his browser open.  When, he gets back, he’ll most likely have been logged out because his session data was garbage collected on the server, even though his browser cookie was still there.</p>
<p>Now, let’s change <code>session.cookie_lifetime </code>to 1 hour.  A user who logs in can stay logged in for up to an hour if he clicks away for the whole time.  This is regardless of whether or not he closes/reopens his browser.  If he takes his 30 min. lunch break after working for 15 mins. he will most likely be logged out when he returns, even though his browser cookie had 15 more mins. of life.</p>
<p>Now, keeping <code>session.cookie_lifetime </code>at 1 hour, let’s set <code>session.gc_maxlifetime </code>to 2 hours.  A user who logs in can stay logged in for up to an hour, <em>period</em>.  He does not have to click at all in that time, but he’ll be logged out after an hour.</p>
<p><strong><span style="text-decoration: underline;">The Real “Remember Me” Solution</span></strong></p>
<p>Back to my problem.  At this point, I could’ve just set both directives to something  like 1 year.  But since <code>session.gc_maxlifetime </code>controls garbage collection of session data, I’d have session data up to a year old left on the server!  I did a quick check on the PHP session directory.  There were already several thousand sessions, and that was only for a 24-minute lifetime!</p>
<p>Clearly, this was not how Twitter did it.  A little more digging, and I realized that sites like those do not keep your specific session around for long periods of time.  What they do is set a long-lasting cookie that contains some sort of security token.  From that token, they can authenticate you, and re-create your session, even if your session data has already been removed from the server.  (The cookie name for Twitter is <code>auth_token </code>and looks to have a lifetime of 20 years.)</p>
<p>With the session recreation method, I could control when and how to log out users, if at all.  So this enabled us to give users indefinite sessions, while keeping all session directives at their default values.</p>
<p><strong><span style="text-decoration: underline;">Beyond Session Cookies</span></strong></p>
<p>This only scratches the surface of authentication topics of course.  We didn&#8217;t talk about security implications of the session re-creation method, though I will say that the best security practice against session-based attacks seems to prompt for a password if the user attempts to change or view sensitive account information.  <a href="http://www.linkedin.com">LinkedIn </a>is the first example that comes to mind.</p>
<p>Shortly after implementing this, a request came down from high above to centralize the authentication for our multiple products.  I began to investigate single sign-on (like Google accounts) and federated identity (like OpenID), but those are topics of another post.</p>
<p>Here are a couple blogs that got me on my way to the final solution. Be sure to read the comments:</p>
<ul>
<li><a href="http://brian.moonspot.net/2008/05/14/php-session-cookie-refresh/">PHP session cookie refresh</a></li>
<li><a href="http://www.xml.lt/Blog/2009/01/27/Auto-login">Auto-login</a></li>
<li><a href="http://www.adaniels.nl/articles/simple-single-sign-on-for-php/">Simple Single Sign-On for PHP</a></li>
</ul>

<p><a href="http://feedads.g.doubleclick.net/~a/At6krfdkkuyOvR3FA331QHZMztE/0/da"><img src="http://feedads.g.doubleclick.net/~a/At6krfdkkuyOvR3FA331QHZMztE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/At6krfdkkuyOvR3FA331QHZMztE/1/da"><img src="http://feedads.g.doubleclick.net/~a/At6krfdkkuyOvR3FA331QHZMztE/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/DfApqyUQrLs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/09/29/of-php-sessions-cookies-and-authentication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip Of The Day: Avoid MySQL Functions</title>
		<link>http://www.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/</link>
		<comments>http://www.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 18:45:00 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[query cache]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/</guid>
		<description><![CDATA[Since I knew that the MySQL Query Cache used the literal queries as keys, it made sense that MySQL did not cache queries with certain SQL functions in them, such as this one:

1
$sql = &#34;select event_id from events where event_dt &#62;= curdate()&#34;;

Because MySQL knows that this query run today is not the same query when [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.straylightrun.net/2009/03/13/mysql-query-cache-or-vertical-partitioning-intro/">Since I knew</a> that the MySQL Query Cache used the literal queries as keys, it made sense that MySQL did not cache queries with certain SQL functions in them, such as this one:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;select event_id from events where event_dt &gt;= curdate()&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Because MySQL knows that this query run today is not the same query when it is run tomorrow. There are other SQL functions such as <code>rand()</code> and <code>unix_timestamp()</code> that will bypass the query cache. These are <a href="http://dev.mysql.com/doc/refman/5.0/en/query-cache-how.html">listed here</a>.</p>
<p>So I avoid these functions when possible by calculating the value in PHP. For example, I’d rewrite the above query as:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$date</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;select event_id from events where event_dt &gt;= '<span style="color: #006699; font-weight: bold;">$date</span>'&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<p><a href="http://feedads.g.doubleclick.net/~a/zQMKGx_238izVGDZKZEZYcgk44k/0/da"><img src="http://feedads.g.doubleclick.net/~a/zQMKGx_238izVGDZKZEZYcgk44k/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/zQMKGx_238izVGDZKZEZYcgk44k/1/da"><img src="http://feedads.g.doubleclick.net/~a/zQMKGx_238izVGDZKZEZYcgk44k/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/sUPlUKa4IoQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Unit Testing</title>
		<link>http://www.straylightrun.net/2009/08/27/database-unit-testing/</link>
		<comments>http://www.straylightrun.net/2009/08/27/database-unit-testing/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 17:04:52 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/?p=233</guid>
		<description><![CDATA[When I first looked into unit testing, the concept seemed simple enough.  The canonical example seemed to be the sum function.

public function sum&#40;$x, $y&#41;
&#123;
    return $x + $y;
&#125;

And the test.

public function testSum&#40;&#41;
&#123;
    $summer = new Summer&#40;&#41;;
&#160;
    $this-&#62;assertEquals&#40;7, $summer-&#62;sum&#40;3, 4&#41;&#41;;
&#160;
    // and after awhile, [...]]]></description>
			<content:encoded><![CDATA[<p>When I first looked into unit testing, the concept seemed simple enough.  The canonical example seemed to be the sum function.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> sum<span style="color: #009900;">&#40;</span><span style="color: #000088;">$x</span><span style="color: #339933;">,</span> <span style="color: #000088;">$y</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$x</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$y</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And the test.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testSum<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$summer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Summer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">7</span><span style="color: #339933;">,</span> <span style="color: #000088;">$summer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sum</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// and after awhile, trying to break the </span>
    <span style="color: #666666; font-style: italic;">// function turned out to be part of the fun.</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #000088;">$summer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sum</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">7</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #000088;">$summer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sum</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In any case, this was nice and all for arithmetic, but like in any typical web app, I soon ran into the big problem: how do I test the database?</p>
<p>Now, there is a <a href="http://www.phpunit.de/manual/3.4/en/database.html">chapter on database testing in the PHPUnit manual</a> with <a href="http://www.ds-o.com/archives/63-PHPUnit-Database-Extension-DBUnit-Port.html">DBUnit for PHP</a>.  But as I read about those, I saw a lot of documentation about syntax and handling of null values and empty tables. I wondered why I couldn&#8217;t just create a <em>real</em> database and test it with <em>real</em> queries?</p>
<p><strong><span style="text-decoration: underline;">Enter SQLite</span></strong></p>
<p><a href="http://www.sqlite.org/">SQLite</a> is a self-contained, serverless, zero-configuration, ACID-compliant RDBMS.  Since SQLite requires no setup, and runs completely in memory, it makes the perfect database to run self-contained, serverless, automated unit tests against.</p>
<p><strong><span style="text-decoration: underline;">Database Access Abstraction To The Rescue</span></strong></p>
<p>Being able to test seamlessly with a SQLite database in my unit tests and run against a MySQL database in live code required some careful thought about how I went about setting up my classes.  First of all, I created a database access interface with some standard functions like <code>query(), getRows(), startTransaction(), commit()</code>, etc.  (You <em>are</em> using a <a href="http://www.straylightrun.net/2009/04/30/who-needs-a-database-abstraction-layer-anyway/">database access class</a>, aren&#8217;t you?)  Then, I implemented the interface with a MySQL implementation, and an SQLite implementation.</p>
<p>Since there are places in the code that takes advantage of MySQL specific features, I had to emulate these features in my SQLite driver.  For example, there was no <a href="http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_lpad"><code>lpad()</code></a> function in SQLite.  Fortunately, thanks to the magic of <a href="http://us3.php.net/manual/en/function.sqlite-create-function.php"><code>createFunction()</code></a>, I could create a SQLite User-Defined Function.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> lpad<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$numchars</span><span style="color: #339933;">,</span> <span style="color: #000088;">$char</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #990000;">str_pad</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$numchars</span><span style="color: #339933;">,</span> <span style="color: #000088;">$char</span><span style="color: #339933;">,</span> STR_PAD_LEFT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$sqlite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createFunction</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lpad'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'lpad'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Some of the MySQL bells and whistles are of course missing, such as <a href="http://www.straylightrun.net/2009/02/09/tip-of-the-day-on-duplicate-key-update/"><code>ON DUPLICATE KEY UPDATE</code></a>. With some fancy query re-writing, I got those MySQL queries working with SQLite.  Here is my current <a href="http://www.straylightrun.net/wp-content/uploads/2009/08/Database.phps">SQLite database access class in its entirety</a>.</p>
<p><strong><span style="text-decoration: underline;">Dependency Injection FTW!</span></strong></p>
<p>Now, that I had a MySQL database driver, and an equivalent SQLite database driver, I needed a way to get my business objects to use the SQLite version in a test, and the MySQL version during real execution.  If only there was a pattern that let me &#8220;inject&#8221; the proper database dependency into the object.  Well, this is exactly what <a href="http://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> is!</p>
<p>Instead of instantiating a database driver within the class, I passed the database object in the constructor.  There are other ways to pass in the object, such as with a setter method, or with a global registry, but I like constructor the best.  So the class might look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Customer
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_db</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$db</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong><span style="text-decoration: underline;">Writing The Test</span></strong></p>
<p>With the database access classes in place set to be injected into my classes, I could test functions that persisted data to the database, and then <em>actually</em> inspect the database.  There was no XML data files.  There was no database testing DSL.  There was only plain ol&#8217; SQL.</p>
<p>Here is a simplified function that saves fictional customer data, and a test for it.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> save<span style="color: #009900;">&#40;</span><span style="color: #000088;">$firstName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lastName</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;INSERT INTO customers (first_name, last_name) VALUES (?, ?)&quot;</span><span style="color: #339933;">,</span> 
        <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$firstName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lastName</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastInsertId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And the test.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> CustomerTest <span style="color: #000000; font-weight: bold;">extends</span> PHPUnit_Framework_TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_db</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Test_Database<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;CREATE TABLE customers (first_name, last_name_);&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;DROP TABLE customers&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testSave<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$customer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Customer<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$customer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Mickey&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;Mouse&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// test that customer is saved to DB</span>
        <span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRows</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT * FROM customers&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Mickey&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'first_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Mouse&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'last_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><span style="text-decoration: underline;"><strong>One Last Thing</strong></span></p>
<p>This method could get to be overkill in certain situations as you write tons of SQL to set up your tests.  But even then I find it preferable to setting up XML or CSV data.  As far as mocking out a database with some sort of Mock Object, I still maintain, why use a mock and a DSL when you can use the real thing?  This has worked well for me so far.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/ULmoONQNzNXglj40E5ld5LiWi0I/0/da"><img src="http://feedads.g.doubleclick.net/~a/ULmoONQNzNXglj40E5ld5LiWi0I/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ULmoONQNzNXglj40E5ld5LiWi0I/1/da"><img src="http://feedads.g.doubleclick.net/~a/ULmoONQNzNXglj40E5ld5LiWi0I/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/978iiywrvO4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/08/27/database-unit-testing/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Slides From OINK-PUG, My Road To Test-Driven Development</title>
		<link>http://www.straylightrun.net/2009/08/21/slides-from-oink-pug-my-road-to-test-driven-development/</link>
		<comments>http://www.straylightrun.net/2009/08/21/slides-from-oink-pug-my-road-to-test-driven-development/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 22:58:08 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[talks]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[test driven development]]></category>
		<category><![CDATA[test first]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/2009/08/21/slides-from-oink-pug-my-road-to-test-driven-development/</guid>
		<description><![CDATA[This past Thursday I gave a short talk at the monthly OINK-PUG meeting about how I discovered the Test-Driven Development Kool-Aid®.&#160; I knew about TDD years before I actually started doing it.&#160; I tried to start several times, and never kept it going.&#160; About a year ago, while developing a web service with no screens, [...]]]></description>
			<content:encoded><![CDATA[<p>This past Thursday I gave a short talk at the monthly <a href="http://www.oink-pug.org">OINK-PUG</a> meeting about how I discovered the Test-Driven Development Kool-Aid®.&nbsp; I knew about TDD years before I actually started doing it.&nbsp; I tried to start several times, and never kept it going.&nbsp; About a year ago, while developing a web service with no screens, the light bulb went on and gave me the idea for this talk.</p>
<blockquote><p>In which I give a short introduction to unit testing, and then outline the story that finally turned on the light bulb about real test-driven development and test first for me. The third part of the talk gives an introduction to Dependency Injection (DI), an integral part to unit testing. </p>
</blockquote>
<div style="text-align: left; width: 425px" id="__ss_1890999"><a style="margin: 12px 0px 3px; display: block; font: 14px helvetica,arial,sans-serif; text-decoration: underline" title="My Road To Test Driven Development" href="http://www.slideshare.net/gerrys0/my-road-to-test-driven-development">My Road To Test Driven Development</a><embed height="355" type="application/x-shockwave-flash" width="425" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=test-driven-development-090821123047-phpapp01&amp;stripped_title=my-road-to-test-driven-development" allowfullscreen="true" allowscriptaccess="always"></embed>
<div style="font-family: tahoma,arial; height: 26px; font-size: 11px; padding-top: 2px">View more <a style="text-decoration: underline" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration: underline" href="http://www.slideshare.net/gerrys0">Gerard Sychay</a>.</div>
</div>

<p><a href="http://feedads.g.doubleclick.net/~a/j6BM9iePtLE5oLRtqbNzidlsTTM/0/da"><img src="http://feedads.g.doubleclick.net/~a/j6BM9iePtLE5oLRtqbNzidlsTTM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/j6BM9iePtLE5oLRtqbNzidlsTTM/1/da"><img src="http://feedads.g.doubleclick.net/~a/j6BM9iePtLE5oLRtqbNzidlsTTM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/aEEz84T5sr4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/08/21/slides-from-oink-pug-my-road-to-test-driven-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coworking In Cincinnati</title>
		<link>http://www.straylightrun.net/2009/08/02/coworking-in-cincinnati/</link>
		<comments>http://www.straylightrun.net/2009/08/02/coworking-in-cincinnati/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 19:39:24 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Career]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[cincinnati]]></category>
		<category><![CDATA[coworking]]></category>
		<category><![CDATA[indyhall]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/2009/08/02/coworking-in-cincinnati/</guid>
		<description><![CDATA[A coworking trend is sweeping the nation and I am involved in bringing it to Cincinnati.&#160; I don&#8217;t know if I&#8217;ve ever undertaken something that requires so much time and effort outside of my day job before (except for Zipscene, which subsequently became my day job).&#160; But we&#8217;ll take it slowly and see where it [...]]]></description>
			<content:encoded><![CDATA[<p>A coworking trend is sweeping the nation and I am involved in bringing it to Cincinnati.&nbsp; I don&#8217;t know if I&#8217;ve ever undertaken something that requires so much time and effort outside of my day job before (except for Zipscene, which subsequently became my day job).&nbsp; But we&#8217;ll take it slowly and see where it goes.</p>
<p>One of the most successful and respected coworking space (from what I have gathered on the interweb anyway) is <a href="http://www.indyhall.org/">Independents Hall in Philadelphia</a>. Fortunately, in true coworking spirit, they have done a great job of <a href="http://www.indyhall.org/blog/">blogging about their progress</a> and I have been leaning heavily on it as a resource.&nbsp; </p>
<p>But enough of that for now.&nbsp; I want to save some of this for the <a href="http://www.cincycoworks.com/">Cincinnati Coworks</a> blog itself, whenever I get around to setting it up. </p>
<p>Some other coworking resources.</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Coworking">Coworking on Wikipedia</a></li>
<li><a href="http://coworking.pbworks.com/">The coworking wiki</a></li>
<li><a href="http://search.twitter.com/search?q=coworking">The coworking buzz</a></li>
</ul>

<p><a href="http://feedads.g.doubleclick.net/~a/ycAwn8lARBJ7U75Hxp6sS7A48Uo/0/da"><img src="http://feedads.g.doubleclick.net/~a/ycAwn8lARBJ7U75Hxp6sS7A48Uo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ycAwn8lARBJ7U75Hxp6sS7A48Uo/1/da"><img src="http://feedads.g.doubleclick.net/~a/ycAwn8lARBJ7U75Hxp6sS7A48Uo/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/UNMr9e3qdDI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/08/02/coworking-in-cincinnati/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Storing Apache Virtual Hosts In A Database</title>
		<link>http://www.straylightrun.net/2009/07/31/storing-apache-virtual-hosts-in-a-database/</link>
		<comments>http://www.straylightrun.net/2009/07/31/storing-apache-virtual-hosts-in-a-database/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 20:29:04 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apr]]></category>
		<category><![CDATA[dbd]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[redhat enterprise]]></category>
		<category><![CDATA[rhel]]></category>
		<category><![CDATA[virtual host]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/?p=219</guid>
		<description><![CDATA[At work, we had set up some wildcard virtual hosts in Apache config, and that got us by for quite some time.  But the time came when we needed finer-grained control of where to send incoming requests for different domains.  I needed to store my virtual hosts in a Mysql database, mapping domains to project [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we had set up some wildcard virtual hosts in Apache config, and that got us by for quite some time.  But the time came when we needed finer-grained control of where to send incoming requests for different domains.  I needed to store my virtual hosts in a Mysql database, mapping domains to project directories.</p>
<p>I&#8217;ll spare you the problems I ran into and overcame, and just list the steps to get this done.  These instructions are based on a 64-bit, RHEL 5 server running the pre-packaged Apache server.  So if you follow these instructions on a different setup, of course, filenames, directories, versions, etc. may differ.</p>
<p><strong><span style="text-decoration: underline;">Install mod_vhost_dbd</span></strong></p>
<p>Download <a href="http://code.google.com/p/dbd-modules/"><code>dbd-modules</code></a> from Google Code.  This is a great piece of code in the form of an Apache module that uses <a href="http://httpd.apache.org/docs/2.2/mod/mod_dbd.html"><code>mod_dbd</code></a> and a DBD Mysql (or other database) driver to fetch the <code>DocumentRoot </code>for a given domain from a database.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% wget http://dbd-modules.googlecode.com/files/dbd-modules-1.0.5.zip</pre></div></div>

<p>Unzip the archive in a directory. As indicated on the website, <a href="http://code.google.com/p/dbd-modules/wiki/Building">build and install the module</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% apxs -c mod_vhost_dbd.c
% apxs -i mod_vhost_dbd.la</pre></div></div>

<p>This places <code>mod_vhost_dbd.so </code>in <code>/usr/lib64/httpd/modules</code>.  Enable both this module and <code>mod_dbd </code>by adding two lines to <code>httpd.conf</code>, or equivalently creating a new include file in<code> /etc/httpd/conf.d</code> containing these lines.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">LoadModule dbd_module modules/mod_dbd.so
LoadModule vhost_dbd_module modules/mod_vhost_dbd.so</pre></div></div>

<p>In true unit fashion, now might be a good time to restart Apache, just so you can be sure everything is working up to this point.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% service httpd restart</pre></div></div>

<p><strong><span style="text-decoration: underline;">Install Mysql DBD Driver to APR</span></strong></p>
<p>Unfortunately, on my system, the Mysql DBD driver was nowhere to be found.  I had to rebuild Apache Portable Runtime (APR) utils with the Mysql driver enabled.</p>
<p>Download <a href="http://apr.apache.org/"><code>apr</code></a> and <a href="http://apr.apache.org/"><code>apr-util</code></a> from Apache.  Note these are not the latest versions, but the versions that <span style="text-decoration: line-through;">matched the packages in</span> worked for RHEL 5.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% wget http://archive.apache.org/dist/apr-1.2.8.tar.bz2
% wget http://archive.apache.org/dist/apr-util-1.2.8.tar.bz2</pre></div></div>

<p>Unpack and untar these archives in the same parent directory.</p>
<p>Build and install APR.  Now, I do not think this is absolutely necessary, but it seems like a good idea to keep the versions in sync.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% ./configure --prefix=/usr
% make
% make install</pre></div></div>

<p>Build and install <code>apr-util</code>.  Due to licensing issues, <code>apr-util </code>does not actually contain the Mysql DBD driver until <code>apr-util-1.2.12</code>.  Prior to that version, it must be downloaded separately, and the configure script rebuilt.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% wget http://apache.webthing.com/svn/apache/apr/apr_dbd_mysql.c
% ./buildconf --with-apr=../apr-1.2.7</pre></div></div>

<p>Now for the three commands every Linux admin loves.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% ./configure --prefix=/usr --with-apr=/usr --libdir=/usr/lib64 --with-expat=builtin --with-ldap-include=/usr/include --with-ldap-lib=/usr/lib64 --with-ldap=ldap --with-mysql
% make
% make install</pre></div></div>

<p>The first time I tried this, Apache could not find any LDAP-related modules.  Adding those configure switches seemed to do the trick.  Restart Apache.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% service httpd restart</pre></div></div>

<p>Apache should now be able to query a Mysql database to get the <code>DocumentRoot </code>for a domain.  My <code>VirtualHost</code> block looked something like this.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
    ServerName *.example.com
    DocumentRoot &quot;/path/to/default/document/root&quot;
&nbsp;
    DBDriver mysql
    DBDParams host=localhost,user=root,pass=secret,dbname=vhosts
&nbsp;
    DBDocRoot &quot;SELECT path FROM vhosts WHERE host = %s&quot;  HOSTNAME
&lt;/VirtualHost&gt;</pre></div></div>

<p>For more details and instructions on <a href="http://code.google.com/p/dbd-modules/wiki/mod_vhost_dbd"><code>mod_vhost_dbd</code> configuration directives, read the project wiki</a>.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/LghO9wU9l5aQe0M3nTvV1oQQT6Y/0/da"><img src="http://feedads.g.doubleclick.net/~a/LghO9wU9l5aQe0M3nTvV1oQQT6Y/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/LghO9wU9l5aQe0M3nTvV1oQQT6Y/1/da"><img src="http://feedads.g.doubleclick.net/~a/LghO9wU9l5aQe0M3nTvV1oQQT6Y/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/IdN_6FUvsyo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/07/31/storing-apache-virtual-hosts-in-a-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgrading PHP 5.1 on CentOS 5.3</title>
		<link>http://www.straylightrun.net/2009/07/15/upgrading-php-5-1-on-centos-5-3/</link>
		<comments>http://www.straylightrun.net/2009/07/15/upgrading-php-5-1-on-centos-5-3/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 17:05:37 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[redhat enterprise]]></category>
		<category><![CDATA[rhel]]></category>
		<category><![CDATA[yum]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/2009/07/15/upgrading-php-5-1-on-centos-5-3/</guid>
		<description><![CDATA[To test things on our RHEL 5 production servers, I fire up CentOS 5 in VMWare.&#160; While we build PHP 5.2 manually in production, I try to avoid doing so just for testing. Unfortunately, CentOS 5 is packaged with PHP 5.1 by default which becomes a big difference between my testing and production environments.&#160; Fortunately, [...]]]></description>
			<content:encoded><![CDATA[<p>To test things on our RHEL 5 production servers, I fire up CentOS 5 in VMWare.&nbsp; While we build PHP 5.2 manually in production, I try to avoid doing so just for testing. Unfortunately, CentOS 5 is packaged with PHP 5.1 by default which becomes a big difference between my testing and production environments.&nbsp; Fortunately, there is a CentOS yum repository out there with PHP 5.2.&nbsp; I thought I&#8217;d document this here for anyone else with the same problem.</p>
<p>The solution I found starts with <a href="http://www.centos.org/modules/newbb/viewtopic.php?topic_id=19290&amp;forum=38">this thread about upgrading PHP on the CentOS forums</a>.&nbsp; To summarize, run these commands:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% cd /etc/yum.repos.d
% wget http://dev.cnetos.org/centos/5/CentOS-Testing.repo</pre></div></div>

<p>Then, edit the .repo file and set the <code>"enabled"</code> value to <code>"1"</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% yum list available php
Available Packages
php.i386                                 5.2.6-2.el5s2          c5-testing</pre></div></div>


<p><a href="http://feedads.g.doubleclick.net/~a/oD6eBujf4am3v1xbiPT6_7_Xf2s/0/da"><img src="http://feedads.g.doubleclick.net/~a/oD6eBujf4am3v1xbiPT6_7_Xf2s/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/oD6eBujf4am3v1xbiPT6_7_Xf2s/1/da"><img src="http://feedads.g.doubleclick.net/~a/oD6eBujf4am3v1xbiPT6_7_Xf2s/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/w3WT_augoSY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/07/15/upgrading-php-5-1-on-centos-5-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip Of The Day: Removing .htaccess</title>
		<link>http://www.straylightrun.net/2009/06/17/tip-of-the-day-removing-htaccess/</link>
		<comments>http://www.straylightrun.net/2009/06/17/tip-of-the-day-removing-htaccess/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 20:48:21 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/?p=205</guid>
		<description><![CDATA[At work, every project has an .htaccess file containing at the least some mod_rewrite rules.  This way, all I need to do to run a project is check it out of version control.  I don&#8217;t need to modify my local Apache configuration.
But turning this option on and allowing .htaccess files may be a performance hit. [...]]]></description>
			<content:encoded><![CDATA[<p>At work, every project has an <code>.htaccess</code> file containing at the least some <code>mod_rewrite </code>rules.  This way, all I need to do to run a project is check it out of version control.  I don&#8217;t need to modify my local Apache configuration.</p>
<p>But turning this option on and allowing <code>.htaccess</code> files may be a performance hit.  More specifically, enabling the <code><a href="http://httpd.apache.org/docs/2.2/mod/core.html#allowoverride">AllowOverride</a> </code>option in Apache is a performance hit.  The <a href="http://httpd.apache.org/docs/2.2/misc/perf-tuning.html">Apache docs</a> sums up the problem best:</p>
<blockquote><p>
&#8220;Wherever in your URL-space you allow overrides (typically <code>.htaccess</code> files) Apache will attempt to open <code>.htaccess</code> for each filename component. For example,</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">DocumentRoot /www/htdocs
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Directory</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   AllowOverride all
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>and a request is made for the URI <code>/index.html</code>. Then Apache will attempt to open <code>/.htaccess</code>, <code>/www/.htaccess</code>, and <code>/www/htdocs/.htaccess</code>.&#8221;
</p></blockquote>
<p>So I disabled all <code>.htaccess </code>files in production, and inserted each file&#8217;s individual <code>mod_rewrite </code>rules into the main Apache config file. After a quick <a href="http://www.straylightrun.net/2009/04/23/apache-bench/">Apache Bench</a> run, one project looked around 3% faster. Note that there are a few other useful optimizations on that page.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/GgjmeqdWy0MwwjS_kna5Y2gqwQM/0/da"><img src="http://feedads.g.doubleclick.net/~a/GgjmeqdWy0MwwjS_kna5Y2gqwQM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/GgjmeqdWy0MwwjS_kna5Y2gqwQM/1/da"><img src="http://feedads.g.doubleclick.net/~a/GgjmeqdWy0MwwjS_kna5Y2gqwQM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/p_VcDlsAFNQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/06/17/tip-of-the-day-removing-htaccess/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What Is Software?</title>
		<link>http://www.straylightrun.net/2009/06/13/what-is-software/</link>
		<comments>http://www.straylightrun.net/2009/06/13/what-is-software/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 20:26:26 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Career]]></category>
		<category><![CDATA[alchemy]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[craft]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[engineering]]></category>
		<category><![CDATA[profession]]></category>
		<category><![CDATA[science]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[title]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/2009/06/13/what-is-software/</guid>
		<description><![CDATA[Long ago, I concluded that software is in fact, among art, science, and engineering, closest to art.&#160; But I had never really considered software as craft.&#160; The Manifesto for Software Craftsmanship has rekindled a debate on software as craft.&#160; That may yet be the best classification of our trade, but I&#8217;m sure it won&#8217;t be [...]]]></description>
			<content:encoded><![CDATA[<p>Long ago, I concluded that software is in fact, among art, science, and engineering, closest to art.&nbsp; But I had never really considered software as craft.&nbsp; The <a href="http://manifesto.softwarecraftsmanship.org/">Manifesto for Software Craftsmanship</a> has rekindled a debate on software as craft.&nbsp; That may yet be the best classification of our trade, but I&#8217;m sure it won&#8217;t be the last.</p>
<p><u><strong>Let&#8217;s Start From The Beginning</strong></u></p>
<p>Let&#8217;s back up a minute.&nbsp; What is software?&nbsp; Is it art?&nbsp; Science?&nbsp; Engineering?&nbsp; Craft?&nbsp; When in doubt, the dictionary is a good place to start.</p>
<blockquote><p><strong>engineering </strong><em>-noun</em> the art or science of making practical application of the knowledge of pure sciences, as physics or chemistry, as in the construction of engines, bridges, buildings, mines, ships, and chemical plants.</p>
</blockquote>
<p>Software has never felt much like engineering to me, maybe because there&#8217;s no calculus involved (usually).&nbsp; There are of course parallels in resource trade-offs, input/output, etc.&nbsp; But to me there is something inherently different between building a bridge, or even a stereo, and writing a program.&nbsp; </p>
<blockquote><p>Software development is still more a craft than an engineering discipline. This is primarily because of a lack of rigor in the critical processes of validating and improving a design.</p>
<p>- <em><a href="http://www.developerdotstar.com/mag/articles/reeves_design.html">Jack Reeves, What Is Software Design?</a></em></p>
</blockquote>
<p>According to Reeves, if we adjust our definition of things slightly, and see that coding is really equivalent to the design that takes place before engineering, it can start to look like other engineering disciplines.&nbsp; But tools (i.e. languages) and coding and testing processes need to evolve much more before that becomes true.</p>
<blockquote><p><strong>art </strong><em>-noun</em> the quality, production, expression, or realm, according to aesthetic principles, of what is beautiful, appealing, or of more than ordinary significance.</p></blockquote>
<p>Software, which is so technical, as art has always appealed in an esoteric sort of way.&nbsp; They say that artists will destroy the first 100 pieces that they do. In the same way, many programmers fight the urge to rewrite something they&#8217;ve written, almost immediately after it&#8217;s completed.&nbsp; I know I do.&nbsp; But fundamentally speaking, the problem with this analog is that while art can exist for art&#8217;s sake, software is usually more practical.&nbsp; That is, even if I write something for fun, I still want it to at least <em>do something</em>.</p>
<blockquote><p><strong>science </strong><em>-noun</em> a branch of knowledge or study dealing with a body of facts or truths systematically arranged and showing the operation of general laws.</p>
</blockquote>
<p>If I&#8217;m not convinced of software as an applied science like engineering, I don&#8217;t see how software as science can be so.&nbsp; In that sense, it falls to the same problem as art: science may exists for science&#8217;s sake &#8211; to discover new knowledge &#8211; but for software, at the end of the day, there always seems to be a customer waiting.</p>
<blockquote><p><strong>craft </strong><em>-noun</em> an art, trade, or occupation requiring special skill, esp. manual skill.</p>
</blockquote>
<p>Oh, but I like this one.&nbsp; It allows us to impose the special skills that is the craft.&nbsp; It leaves room for the creativity that is so essential for success &#8211; and rewarding.&nbsp; It speaks to the practical requirements that usually pay the bills at the end of the day and (hopefully) make life easier for someone.</p>
<p>If we consider software as craft, we cannot avoid talking about masters and apprentices.&nbsp; People often forget that there are apprentices around today.&nbsp; It used to be that if you wanted to become an electrician, plumber, or home inspector, you must have first trained as an apprentice.&nbsp; Only after many (usually unpaid) months of apprenticeship under a master could you get a license to work.&nbsp; These days, there are ways around that requirements, and apprenticeship is often found only in union crews.&nbsp; (And in unions it seems that politics has overtaken the original goal: to further the craft.)&nbsp; But I digress.</p>
<p>The main problem with this is the reason there is a market for this type of qualifying: it is the law.&nbsp; You technically cannot pull a permit on a home&#8217;s electrical (except your own) unless you are licensed.&nbsp; You cannot get your license until you apprentice or take a test.&nbsp; So would it be better or worse if there was a law requiring all software developers to get licensed before practicing their craft?&nbsp; I&#8217;m certain quality would go up.&nbsp; But the profession suddenly becomes less accessible.</p>
<p><u><strong>A Rose By Any Other Name&#8230;</strong></u></p>
<p>While we&#8217;re on the subject, what do software professionals like to be called?&nbsp; Software engineers?&nbsp; Developers?&nbsp; Programmers?&nbsp; Artisans?&nbsp; Architects?&nbsp; I hate using the title &#8220;software engineer&#8221; (see above).&nbsp; Besides, &#8220;software artisan&#8221; is closer, but does not sound any less pretentious.&nbsp; Personally, I prefer &#8220;developer&#8221; if I&#8217;m in the company of those who know what that means, and for everyone else, &#8220;programmer&#8221; will do.</p>
<p>I am reminded of &#8220;<a href="http://technically.us/code/x/the-human-programmer">The human programmer</a>&#8221; that compares programmers&#8217; quest for a title to musicians&#8217; and writers&#8217;.</p>
<blockquote><p>Maybe programmers are just like the 1950s musicians that lacked &#8230; confidence, snatching desperately for public nobility. Thus far our attempts at title theft have been less successful than theirs, though not for lack of trying (e.g. software developer / architect / engineer). Like musicians, our work requires not only talent but years of practice, and we see ourselves as “different.” The average person cannot walk up to a piano, or a computer keyboard, and produce anything of value. Writers? Throw them in here too, certainly. Are reporters not a little too serious about being called “journalists”? Of course, this line of thought would annoy both of those professions, them being old, established, and respected compared to programming.</p></blockquote>
<p><u><strong>Software As&#8230;?</strong></u></p>
<p>Of course, none of this really matters.&nbsp; We still go about our jobs every day doing what we do and <a href="http://duartes.org/gustavo/blog/post/lucky-to-be-a-programmer">enjoying it</a>.&nbsp; But we forget sometimes that software as a profession is only decades old!&nbsp; Compared to other professions in art, science, or engineering, software is in its infancy!&nbsp; Someday I think a classification will be agreed upon.&nbsp; In the meantime, I&#8217;ll throw one more definition out there.</p>
<blockquote><p><strong>alchemy </strong><em>-noun</em> any magical power or process of transmuting a common substance, usually of little value, into a substance of great value.</p>
</blockquote>
<p>I like the idea of turning nothing but keystrokes and time into something of great value to someone.&nbsp; Software alchemist.&nbsp; I&#8217;m ordering new business cards.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/z1HD9hROQw2FaakZ_B4R6ntthBc/0/da"><img src="http://feedads.g.doubleclick.net/~a/z1HD9hROQw2FaakZ_B4R6ntthBc/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/z1HD9hROQw2FaakZ_B4R6ntthBc/1/da"><img src="http://feedads.g.doubleclick.net/~a/z1HD9hROQw2FaakZ_B4R6ntthBc/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/76FMPocpXH0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/06/13/what-is-software/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Running IE6 Virtual PC Image in VMware</title>
		<link>http://www.straylightrun.net/2009/05/13/running-ie6-virtual-pc-image-in-vmware/</link>
		<comments>http://www.straylightrun.net/2009/05/13/running-ie6-virtual-pc-image-in-vmware/#comments</comments>
		<pubDate>Wed, 13 May 2009 14:47:33 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[virtual pc]]></category>
		<category><![CDATA[virtualization]]></category>
		<category><![CDATA[vmware]]></category>
		<category><![CDATA[windows xp]]></category>
		<category><![CDATA[winxp]]></category>

		<guid isPermaLink="false">http://www.straylightrun.net/2009/05/13/running-ie6-virtual-pc-image-in-vmware/</guid>
		<description><![CDATA[Though I have heard good things about Parallels and VirtualBox, I have always been a user of VMware.&#160; In particular, VMware Workstation.&#160; Workstation is great for firing up multiple Linux instances and testing out load-balancing or proxying scenarios.&#160; I haven&#8217;t really figured out any use for Windows VM&#8217;s other than testing IE6.&#160; 
While there are [...]]]></description>
			<content:encoded><![CDATA[<p>Though I have heard good things about <a href="http://www.parallels.com">Parallels</a> and <a href="http://www.virtualbox.org">VirtualBox</a>, I have always been a user of <a href="http://www.vmware.com">VMware</a>.&nbsp; In particular, <a href="http://www.vmware.com/products/ws/">VMware Workstation</a>.&nbsp; Workstation is great for firing up multiple Linux instances and testing out load-balancing or proxying scenarios.&nbsp; I haven&#8217;t really figured out any use for Windows VM&#8217;s other than testing IE6.&nbsp; </p>
<p>While there are a few Virtual PC hard disk images (.vhd) for Windows XP around, VMware cannot directly import .vhd files.&nbsp; It needs the actual Virtual PC virtual machine file (.vmc).&nbsp; After again losing my Windows XP virtual machine that I use for IE6 testing, I thought I&#8217;d document the process of running Windows XP in VMware so I don&#8217;t have to figure it out again the next time it happens.&nbsp; </p>
<p>Note: though these instructions are for VMware Workstation, some of this may apply to the <a href="http://www.vmware.com/products/player/">free VMware Player</a>.</p>
<ol>
<li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=21EABB90-958F-4B64-B5F1-73D0A413C8EF&amp;displaylang=en">Download the IE6 Virtual PC Virtual Hard Disk (.vhd) image from Microsoft</a>.
<li><a href="http://www.microsoft.com/windows/virtual-pc/">Download and install Virtual PC from Microsoft</a>, if you don&#8217;t have it already.
<li>Start Virtual PC.&nbsp; If you have no virtual machines, you will get the New Virtual Machine Wizard.&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard1.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="163" alt="vmcwizard1" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard1-thumb.jpg" width="228" border="0"></a>
<li>Select &#8220;Use default settings to create a new virtual machine&#8221;. Click Next.<br />&nbsp;<a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="163" alt="vmcwizard2" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard2-thumb.jpg" width="228" border="0"></a>
<li>Pick a location to save your Virtual PC virtual machine.&nbsp; This should be the location you will create the VMware virtual machine.&nbsp; I keep all my VM&#8217;s in the same directory with meaningful names.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard3.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="163" alt="vmcwizard3" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard3-thumb.jpg" width="228" border="0"></a>
<li>Click Finish to create the new virtual machine.&nbsp; <br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard4.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="163" alt="vmcwizard4" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmcwizard4-thumb.jpg" width="228" border="0"></a>
<li>If you selected &#8220;When I click Finish, open Settings,&#8221; in the previous step, you will see the settings dialog.&nbsp; If you did not, select the new VM and click Settings.&nbsp; Select &#8220;Virtual hard disk file:&#8221; and find the .vhd file you downloaded in step 1.&nbsp; After finding it, click OK.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/startvmc1.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="170" alt="startvmc1" src="http://www.straylightrun.net/wp-content/uploads/2009/05/startvmc1-thumb.jpg" width="228" border="0"></a>
<li>You should see your VM in the Virtual PC Console.&nbsp; <br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/startvmc2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="167" alt="startvmc2" src="http://www.straylightrun.net/wp-content/uploads/2009/05/startvmc2-thumb.jpg" width="228" border="0"></a>
<li>Select your VM and click Start.&nbsp; Your Windows XP virtual machine should boot in its own window.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/startvmc3.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="144" alt="startvmc3" src="http://www.straylightrun.net/wp-content/uploads/2009/05/startvmc3-thumb.jpg" width="228" border="0"></a>
<li>Shut down the virtual machine using the Start button.&nbsp; Then exit out of Virtual PC.&nbsp; Start VMware Workstation.&nbsp; Once it&#8217;s started, select &#8220;Import or Export&#8230;&#8221; from the &#8220;File&#8221; menu.&nbsp; You should see the Conversion Wizard.&nbsp; Click Next. <br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard0.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="199" alt="vmxwizard0" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard0-thumb.jpg" width="228" border="0"></a>&nbsp;&nbsp;
<li>You are at Step 1 of the conversion. Click Next to select a Source Type. Under &#8220;Select the type of source you want to use:&#8221;, select Other.&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard1.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="199" alt="vmxwizard1" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard1-thumb.jpg" width="228" border="0"></a>
<li>Under &#8220;Source VM or image:&#8221;, find the Virtual PC (.vmc) file you created earlier.&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="199" alt="vmxwizard2" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard2-thumb.jpg" width="228" border="0"></a>
<li>Select &#8220;Convert all disks and maintain size.&#8221; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard3.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard3" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard3-thumb.jpg" width="228" border="0"></a>
<li>You are at Step 2 of the conversion. Click Next to select a destination type.&nbsp; Under &#8220;Select the destination type,&#8221; select &#8220;Other Virtual Machine.&#8221;&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard5.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard5" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard5-thumb.jpg" width="228" border="0"></a>
<li>Under &#8220;Virtual machine name,&#8221; fill in a meaningful name.&nbsp; Under &#8220;Location:&#8221;, find the place you want to store your virtual machine.&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard6.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard6" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard6-thumb.jpg" width="228" border="0"></a>
<li>The wizard tells you that the source files are in Microsoft virtual disk (.vhd) format.&nbsp; Under &#8220;How do you want to convert them?&#8221;, select &#8220;Import and convert (full-clone).&#8221;&nbsp; Under &#8220;Disk Allocation,&#8221; Select &#8220;Allow virtual disk files to expand.&#8221;&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard7.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard7" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard7-thumb.jpg" width="228" border="0"></a>
<li>The next step allows you to configure your VM networking.&nbsp; You should probably stick to the default of 1 NIC, bridged, that connects at power on.&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard8.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard8" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard8-thumb.jpg" width="228" border="0"></a>
<li>Step 3 allows for some VMware customisation.&nbsp; You definitely want to install the VMware Tools.&nbsp; Click Next.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard9.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard9" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard9-thumb.jpg" width="228" border="0"></a>
<li>You&#8217;re Virtual PC image is ready to be converted to VMware.&nbsp; Click Finish to begin the conversion!<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard10.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="vmxwizard10" src="http://www.straylightrun.net/wp-content/uploads/2009/05/vmxwizard10-thumb.jpg" width="228" border="0"></a>
<li>Get up from your desk and take a walk around.&nbsp; Go get a cup of coffee.&nbsp;
<li>After the conversion is completed, you should see your new Windows XP virtual machine in VMware Workstation.<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/finished1.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="217" alt="finished1" src="http://www.straylightrun.net/wp-content/uploads/2009/05/finished1-thumb.jpg" width="228" border="0"></a>
<li>Click on &#8220;Power on this virtual machine&#8221; and your Windows XP VM should boot inside of VMware Workstation.&nbsp; You can uninstall Virtual PC at this point, if you want (which is likely, since you&#8217;re running VMware).<br /><a href="http://www.straylightrun.net/wp-content/uploads/2009/05/finished2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="144" alt="finished2" src="http://www.straylightrun.net/wp-content/uploads/2009/05/finished2-thumb.jpg" width="228" border="0"></a>&nbsp;&nbsp; </li>
</ol>

<p><a href="http://feedads.g.doubleclick.net/~a/fTmmn6iWF6ovvlQaGcJjD9mz-qs/0/da"><img src="http://feedads.g.doubleclick.net/~a/fTmmn6iWF6ovvlQaGcJjD9mz-qs/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/fTmmn6iWF6ovvlQaGcJjD9mz-qs/1/da"><img src="http://feedads.g.doubleclick.net/~a/fTmmn6iWF6ovvlQaGcJjD9mz-qs/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/straylightrun/~4/Sax6M7mAcl8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.straylightrun.net/2009/05/13/running-ie6-virtual-pc-image-in-vmware/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
