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

<channel>
	<title>-= n8v =-</title>
	<atom:link href="http://n8v.enteuxis.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://n8v.enteuxis.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Wed, 17 Feb 2010 05:59:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=3.0-alpha</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Compiling dansguardian 2.10.1.1 on Mac OS X Snow Leopard</title>
		<link>http://n8v.enteuxis.org/2010/01/compiling-dansguardian-2-10-1-1-on-mac-os-x-snow-leopard/</link>
		<comments>http://n8v.enteuxis.org/2010/01/compiling-dansguardian-2-10-1-1-on-mac-os-x-snow-leopard/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 07:21:24 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=314</guid>
		<description><![CDATA[I&#8217;m trying the DansGuardian content filtering proxy at home.  But it wouldn&#8217;t compile on my modern Snow Leopard machine.


Salient errors:


String.cpp: In member function ‘off_t String::toOffset()’:
String.cpp:167: warning: format ‘%d’ expects type ‘int*’, but argument 3 has type ‘off_t*’
In file included from HTTPHeader.hpp:38,
              [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m trying the DansGuardian content filtering proxy at home.  But it wouldn&#8217;t compile on my modern Snow Leopard machine.<br />
<span id="more-314"></span></p>

<h4>Salient errors:</h4>

<blockquote><pre>
String.cpp: In member function ‘off_t String::toOffset()’:
String.cpp:167: warning: format ‘%d’ expects type ‘int*’, but argument 3 has type ‘off_t*’
In file included from HTTPHeader.hpp:38,
                 from DownloadManager.hpp:30,
                 from OptionContainer.hpp:27,
                 from ConnectionHandler.hpp:27,
                 from ConnectionHandler.cpp:25:
RegExp.hpp:31:23: error: pcreposix.h: No such file or directory
In file included from HTTPHeader.hpp:38,
                 from DownloadManager.hpp:30,
                 from OptionContainer.hpp:27,
                 from ConnectionHandler.hpp:27,
                 from ConnectionHandler.cpp:25:
RegExp.hpp:82: error: ‘regex_t’ does not name a type
make[2]: *** [dansguardian-ConnectionHandler.o] Error 1
make[2]: *** Waiting for unfinished jobs....
mv -f .deps/dansguardian-String.Tpo .deps/dansguardian-String.Po
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
</pre>
</blockquote>

<p>And a wild goose chase:  don&#8217;t alter your PCRE_LIBS environment variable or you&#8217;ll have trouble like this:</p>

<blockquote><code>ld: in /Developer/SDKs/MacOSX10.5.sdk/usr/include/php/ext/pcre/pcrelib, can't map file, errno=22</blockquote>

<p></code></p>

<h4>What worked:</h4>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">&nbsp;
<span class="co0"># this is the main thing-- help it find pcreposix.h !</span>
<span class="kw3">export</span> <span class="re2">CPPFLAGS</span>=-I<span class="sy0">/</span>Developer<span class="sy0">/</span>SDKs<span class="sy0">/</span>MacOSX10.5.sdk<span class="sy0">/</span>usr<span class="sy0">/</span>include<span class="sy0">/</span>php<span class="sy0">/</span>ext<span class="sy0">/</span>pcre<span class="sy0">/</span>pcrelib
&nbsp;
<span class="co0"># only the last two are my preferences, </span>
<span class="co0"># the others are from the INSTALL doc</span>
&nbsp;
.<span class="sy0">/</span>configure <span class="re5">--localstatedir</span>=<span class="sy0">/</span>var  \
         <span class="re5">--mandir</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>share<span class="sy0">/</span><span class="kw2">man</span><span class="sy0">/</span>  \
         <span class="re5">--bindir</span>=<span class="sy0">/</span>usr<span class="sy0">/</span><span class="kw3">local</span><span class="sy0">/</span>sbin<span class="sy0">/</span> \
         <span class="re5">--with-logdir</span>=<span class="sy0">/</span>usr<span class="sy0">/</span><span class="kw3">local</span><span class="sy0">/</span>dansguardian<span class="sy0">/</span>logs<span class="sy0">/</span> \
         <span class="re5">--enable-email</span>=<span class="kw2">yes</span>
&nbsp;
<span class="kw2">make</span> <span class="re5">-j</span> <span class="nu0">2</span>
<span class="kw2">sudo</span> <span class="kw2">make</span> <span class="kw2">install</span></pre></div></div>


<h2>starting at boot with <code>daemonic</code></h2>

<p>I got <a href="www.squid-cache.org/">squid</a> using <a href="http://fink.sourceforge.net/">Fink</a>, which uses <a href="http://daemonic.sourceforge.net/">daemonic</a> for startup/init scripts.  So hopefully I can use it to start dansguardian at boot too.</p>

<p>I copied the squid XML file and made this one at <var>/sw/etc/daemons/dansguardian.xml</var>:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="sc3"><span class="re1">&lt;service<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;description<span class="re2">&gt;</span></span></span>Dan's Guardian<span class="sc3"><span class="re1">&lt;/description<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;message<span class="re2">&gt;</span></span></span>Dan's Guardian content filter<span class="sc3"><span class="re1">&lt;/message<span class="re2">&gt;</span></span></span>
&nbsp;
<span class="sc3"><span class="re1">&lt;daemon</span> <span class="re0">name</span>=<span class="st0">&quot;dansguardian&quot;</span><span class="re2">&gt;</span></span>
<span class="sc3"><span class="re1">&lt;executable</span> <span class="re0">checkexit</span>=<span class="st0">&quot;true&quot;</span><span class="re2">&gt;</span></span>/usr/local/sbin/dansguardian<span class="sc3"><span class="re1">&lt;/executable<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;configfile<span class="re2">&gt;</span></span></span>/usr/local/etc/dansguardian/dansguardian.conf<span class="sc3"><span class="re1">&lt;/configfile<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;pidfile<span class="re2">&gt;</span></span></span>/var/run/dansguardian.pid<span class="sc3"><span class="re1">&lt;/pidfile<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;/daemon<span class="re2">&gt;</span></span></span>
&nbsp;
<span class="sc3"><span class="re1">&lt;/service<span class="re2">&gt;</span></span></span></pre></div></div>


<p>Now all I have to do is:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">sudo</span> daemonic <span class="kw3">enable</span> dansguardian</pre></div></div>


<p>Looks like it built some nice OS-X-y startup scripts for me in <var>/Library/StartupItems/daemonic-dansguardian</var>.  Here goes rebooting&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2010/01/compiling-dansguardian-2-10-1-1-on-mac-os-x-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Microsoft Visual Studio 2005 to talk to Microsoft SQL Server 2008</title>
		<link>http://n8v.enteuxis.org/2009/12/getting-microsoft-visual-studio-2005-to-talk-to-microsoft-sql-server-2008/</link>
		<comments>http://n8v.enteuxis.org/2009/12/getting-microsoft-visual-studio-2005-to-talk-to-microsoft-sql-server-2008/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:22:30 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[mssql]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=303</guid>
		<description><![CDATA[Problem:

Visual Studio 2005 complains,

Database schema could not be retrieved for this connection.  Please make sure the connection settings are correct and that the database is online.

This server version is not supported.  You must have Microsoft SQL Server 2005 Beta 2 or later.

Except I have MS SQL Server 2008 Express.

Solution:

Download and install this CTP [...]]]></description>
			<content:encoded><![CDATA[<h2>Problem:</h2>

<p>Visual Studio 2005 complains,</p>

<div id="attachment_308" class="wp-caption alignright" style="width: 410px"><a href="http://n8v.enteuxis.org/wp-content/uploads/2009/12/mssql_vs_2005_2008_error1.PNG"><img class="size-medium wp-image-308 " title="mssql_vs_2005_2008_error" src="http://n8v.enteuxis.org/wp-content/uploads/2009/12/mssql_vs_2005_2008_error1.PNG" alt="Error screenshot (read text on left)" width="400" height="64" /></a><p class="wp-caption-text">Error screenshot (read text on left)</p></div>

<blockquote>Database schema could not be retrieved for this connection.  Please make sure the connection settings are correct and that the database is online.

This server version is not supported.  You must have Microsoft SQL Server 2005 Beta 2 or later.</blockquote>

<p>Except I have MS SQL Server 2008 Express.</p>

<h2>Solution:</h2>

<p>Download and install <a href="http://msdn.microsoft.com/en-us/library/cc440724.aspx">this CTP (Community Technology Preview)</a> which addresses the issue.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/12/getting-microsoft-visual-studio-2005-to-talk-to-microsoft-sql-server-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deny access to .svn directories with IIS</title>
		<link>http://n8v.enteuxis.org/2009/11/deny-access-to-svn-directories-with-iis/</link>
		<comments>http://n8v.enteuxis.org/2009/11/deny-access-to-svn-directories-with-iis/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 21:40:38 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[obscurity]]></category>
		<category><![CDATA[rewrite]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=295</guid>
		<description><![CDATA[The problem:

I like using Subversion to deploy web content to production servers.  I check in everything while I&#8217;m working on the development copy, then check out onto the server when it&#8217;s ready.

Subversion creates a .svn directory contain readable copies of all your files, which is bad for server-processed files like .php or .aspx that [...]]]></description>
			<content:encoded><![CDATA[<h3>The problem:</h3>

<p>I like using Subversion to deploy web content to production servers.  I check in everything while I&#8217;m working on the development copy, then check out onto the server when it&#8217;s ready.</p>

<p>Subversion creates a <code>.svn</code> directory contain readable copies of all your files, which is bad for server-processed files like .php or .aspx that you don&#8217;t want readable by, say, <a href="http://en.wikipedia.org/wiki/Google_hacking">Google Hackers</a>.</p>

<p>I have thought about this before but when I went to do it I couldn&#8217;t find any clear guides online.  I did find <a href="http://serverfault.com/questions/23340/ignoring-svn-directories-under-iis/83480#83480">this question at Server Fault</a>, which is a newish sister of <a href="http://stackoverflow.com">Stack Overflow</a>, which reminds me kind of Experts Exchange but without the suck.  Except that in this case the answers sucked.   So I figured it out and added my answer and am posting it here too:
<span id="more-295"></span></p>

<hr />

<p>&#8220;Don&#8217;t do it that way&#8221; does not answer the question.</p>

<p>Practically, I like having a working copy on the production server, because that way I can make quick changes in production (who has never done that?) and check them back in.  It depends on where you want your security/convenience slider, and in many cases this is a good place.</p>

<p>The standard solution in Apacheland is to leave the .svn files there but tell the web server to never serve them.  Here&#8217;s how to do that with IIS 5 through 7 on Windows NT4 through 2008.</p>

<ol>
<li><p>Download and install <a href="http://www.helicontech.com/isapi_rewrite/">ISAPI_Rewrite</a> &#8212; the Lite version will be enough for this purpose.  There are two versions, version 2 and 3.  Use ISAPI_Rewrite3 unless you need to support NT4.    Also, note the extra <a href="http://www.helicontech.com/isapi_rewrite/doc/sysreq.htm">IIS features</a> you need to enable for Win 2008.<br />
<strong>Warning</strong>&#8211; the MSI installer may stop and start IIS.</p></li>
<li><p>Launch the <em>Helicon->ISAPI_Rewrite3->ISAPI_Rewrite Manager</em> app from the Start Menu.  It makes editing the config file (installed in <em>C:\Program Files\Helicon\ISAPI_Rewrite3\httpd.conf</em> by default) easier, but you can also do it by hand.  <strong>note</strong>, the config file in ISAPI_Rewrite2 is named <em>httpd.ini</em> and is read-only by default.</p></li>
<li><p>Add these lines to <em>httpd.conf</em>:</p></li>
</ol>


<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1"># Deny access to Subversion working copy administrative</span>
<span class="co1">#  directories (.svn) and their contents</span>
<span class="kw1">RewriteRule</span> .*/\.svn\b.* . [F,I,O]</pre></div></div>


<p>Now, any request for a .svn directory or its contents will result in a 404 Not Found from the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/11/deny-access-to-svn-directories-with-iis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony log management with `logrotate` on Linux</title>
		<link>http://n8v.enteuxis.org/2009/10/symfony-log-management-with-logrotate-on-linux/</link>
		<comments>http://n8v.enteuxis.org/2009/10/symfony-log-management-with-logrotate-on-linux/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 20:44:34 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=282</guid>
		<description><![CDATA[It sucks when server disks fill up.  I have Nagios set up to notify me well before it&#8217;s a problem, but it happens annoyingly frequently, and it&#8217;s always the same cause:  log files.

Symfony&#8217;s production environments don&#8217;t create logs, but the development environments do, and for one project I had several batch jobs logging [...]]]></description>
			<content:encoded><![CDATA[<p>It sucks when server disks fill up.  I have <a href="http://www.nagios.org/">Nagios</a> set up to notify me well before it&#8217;s a problem, but it happens annoyingly frequently, and it&#8217;s always the same cause:  log files.</p>

<p>Symfony&#8217;s production environments don&#8217;t create logs, but the development environments do, and for one project I had several batch jobs logging to the <var>myproject/log</var> directory.  (Troubleshooting batch jobs without logs is just crazy).</p>

<p>I was going to use <a href="http://www.symfony-project.org/book/1_2/16-Application-Management-Tools#chapter_16_sub_symfony_logs"><code>symfony log:rotate</code></a>, but</p>

<ul>
<li>I would need one cron job for each log</li>
<li>I had permission issues since some of the logs belong to <var>apache</var> and others to <var>root</var></li>
<li>Everything else on the machine, pretty much, is managed with the standard Linux utility <a href="http://linux.die.net/man/8/logrotate"><var>logrotate</var></a>.  Logrotate has been around for about 174 Linux Years, and is common to most distributions.</li>
</ul>

<p>So here&#8217;s how I did it using with <var>logrotate</var>.</p>

<p><span id="more-282"></span></p>

<ol>

    <li><strong>WARNING</strong>:  You might want to make a convenient copy of your log directory before you do this.  I accidently wiped all the logs out while messing with it.
</li>

    <li>Create a file <var>config/myproject.logrotate</var>.  Very simple, I just want it to use the same rotation schedule specified for the whole machine in <var>/etc/logrotate.conf</var>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>myproject<span class="sy0">/</span>log<span class="sy0">/*</span>.log <span class="br0">&#123;</span>
        weekly
        rotate <span class="nu0">4</span>
<span class="br0">&#125;</span></pre></div></div>



</li>

    <li>Check that it will do stuff by running it with the debug flag


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">logrotate <span class="re5">-df</span> config<span class="sy0">/</span>badge.logrotate</pre></div></div>


</li>


    <li>Make a symlink to it in <var>/etc/logrotate.d</var>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">ln</span> <span class="re5">-s</span> <span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>myproject<span class="sy0">/</span>config<span class="sy0">/</span>myproject.logrotate  <span class="sy0">/</span>etc<span class="sy0">/</span>logrotate.d<span class="sy0">/</span>myproject</pre></div></div>



</li>

    <li>Run it the first time manually to rotate your logs and make sure it does the right thing!


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">sudo</span> logrotate <span class="re5">-fv</span> <span class="sy0">/</span>etc<span class="sy0">/</span>logrotate.d<span class="sy0">/</span>myproject</pre></div></div>



</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/10/symfony-log-management-with-logrotate-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MCPD .NET Web Self-Paced Training Kit time estimate summary</title>
		<link>http://n8v.enteuxis.org/2009/08/mcpd-net-web-self-paced-training-kit-time-estimate-summary/</link>
		<comments>http://n8v.enteuxis.org/2009/08/mcpd-net-web-self-paced-training-kit-time-estimate-summary/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 21:30:06 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[hoopjumping]]></category>
		<category><![CDATA[training]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=270</guid>
		<description><![CDATA[

So I have to get a certification to progress in my job, and it needs to involve Microsoft .NET.  OK.  So I&#8217;m working through the MCPD (Microsoft Certified Professional Developer) .NET web development training kit, available at Amazon, 
Barnes and Noble, etc.  In theory it&#8217;s all I need prepare for the 3 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://n8v.enteuxis.org/wp-content/uploads/2009/08/mcpd_training-300x272.jpg" alt="MCPD .NET web development training kit" title="MCPD .NET web development training kit" width="300" height="272" class="alignleft size-medium wp-image-273" style="border:0px; " border="0" /></p>

<p>So I have to get a certification to progress in my job, and it needs to involve Microsoft .NET.  OK.  So I&#8217;m working through the MCPD (Microsoft Certified Professional Developer) .NET web development training kit, available at <a href="http://www.amazon.com/Self-Paced-Training-70-536-70-528-70-547/dp/0735623767">Amazon</a>, 
<a href="http://search.barnesandnoble.com/MCPD-Self-Paced-Training-Kit/Tony-Northrup/e/9780735623767">Barnes and Noble</a>, etc.  In theory it&#8217;s all I need prepare for the 3 exams for the MCPD, 70-536, 70-528, 70-547.</p>

<p>Thoughts so far:</p>

<ol>
<li>C# is surprisingly well-designed.  Especially compared to say, PHP, which was only  <em>designed</em> after the fact.</li>
<li>I LOVE LOVE LOVE the elegant high tech tool metaphor gracing the cover.</li>
<li>I love books instead of training, especially &#8220;online training&#8221;.  But I need to map out a schedule and stick to it or it will get lost amid many other things.  </li>
</ol>

<p>So here, I went through the books and with Perl&#8217;s help, added up the estimates for each section, adding a 10 minute review on each chapter.</p>

<p><span id="more-270"></span></p>

<h2>70-536 Foundations</h2>

<h3>ch 1: Framework Fundamentals  (total:  2:20)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  40 minutes</li>
<li>lesson 3:  40 minutes</li>
<li>lesson 4:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 2: Input  (total:  1:15)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  10 minutes</li>
<li>lesson 4:  15 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 3: Searching  (total:  1:25)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 4: Collections and Generics  (total:  1:55)</h3>

<ul>
<li>lesson 1:  15 minutes</li>
<li>lesson 2:  10 minutes</li>
<li>lesson 3:  30 minutes</li>
<li>lesson 4:  30 minutes</li>
<li>lesson 5:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 5: Serialization  (total:  2:05)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  40 minutes</li>
<li>lesson 3:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 6: Graphics  (total:  2:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>lesson 3:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 7: Threading  (total:  1:50)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  40 minutes</li>
<li>lesson 3:  40 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 8: Application Domains and Services  (total:  1:40)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  25 minutes</li>
<li>lesson 3:  45 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 9: Installing and Configuring Applications  (total:  1:35)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  25 minutes</li>
<li>lesson 3:  15 minutes</li>
<li>lesson 4:  25 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 10: Instrumentation  (total:  1:30)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  20 minutes</li>
<li>lesson 4:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 11: Application Security  (total:  2:40)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  45 minutes</li>
<li>lesson 3:  45 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 12: User and Data Security  (total:  3:40)</h3>

<ul>
<li>lesson 1:  90 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>lesson 3:  90 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 13: Interoperation  (total:  1:10)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 14: Reflection  (total:  1:35)</h3>

<ul>
<li>lesson 1:  15 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  25 minutes</li>
<li>lesson 4:  15 minutes</li>
<li>lesson 5:  10 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 15: Mail  (total:  1:10)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 16: Globalization  (total:  1:10)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  40 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h2>70-528 Web-Based</h2>

<h3>ch 1: Introducing the ASP.NET 2.0 Web Site  (total:  2:20)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>lesson 3:  20 minutes</li>
<li>lesson 4:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 2: Adding and Configuring Server Controls  (total:  1:40)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 3: Exploring Specialized Server Controls  (total:  2:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 4: Using ADO.NET and XML with ASP.NET  (total:  3:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>lesson 3:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 5: Creating Custom Web Controls  (total:  2:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 6: Input Validation and Site Navigation  (total:  2:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 7: ASP.NET State Management  (total:  1:10)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 8: Programming the Web Application  (total:  1:10)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 9: Customizing and Personalizing a Web Application  (total:  3:10)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  45 minutes</li>
<li>lesson 3:  90 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 10: Globalization and Accessibility  (total:  1:20)</h3>

<ul>
<li>lesson 1:  40 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 11: Implementing Authentication and Authorization  (total:  1:40)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  45 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 12: Creating ASP.NET Mobile Web Apps  (total:  1:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 13: Monitoring, Deploying and Caching Apps  (total:  2:00)</h3>

<ul>
<li>lesson 1:  40 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>lesson 3:  40 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h2>70-547 Designing</h2>

<h3>ch 1: Application Requirements and Design  (total:  1:10)</h3>

<ul>
<li>lesson 1:  40 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 2: Decompose Specifications for Developers  (total:  1:25)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  35 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 3: Design Evaluation  (total:  0:30)</h3>

<ul>
<li>lesson 1:  10 minutes</li>
<li>lesson 2:  10 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 4: Creating a User Interface  (total:  2:25)</h3>

<ul>
<li>lesson 1:  90 minutes</li>
<li>lesson 2:  45 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 5: Creating and Choosing Controls  (total:  2:25)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  90 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 6: Data Validation  (total:  2:25)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  90 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 7: Delivering Multimedia  (total:  0:55)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 8: Component Design  (total:  1:10)</h3>

<ul>
<li>lesson 1:  20 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 9: Component Development  (total:  1:00)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  10 minutes</li>
<li>lesson 3:  10 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 10: Reusable Software Components  (total:  1:40)</h3>

<ul>
<li>lesson 1:  90 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 11: Application Logic Layer  (total:  1:10)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  30 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 12: Logging and Monitoring  (total:  1:25)</h3>

<ul>
<li>lesson 1:  40 minutes</li>
<li>lesson 2:  35 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 13: Application Configuration  (total:  1:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 14: Define and Evaluate a Testing Strategy  (total:  1:05)</h3>

<ul>
<li>lesson 1:  30 minutes</li>
<li>lesson 2:  25 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 15: Creating Development Tests  (total:  1:50)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  20 minutes</li>
<li>lesson 3:  20 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 16: Deploying an Application  (total:  2:25)</h3>

<ul>
<li>lesson 1:  45 minutes</li>
<li>lesson 2:  45 minutes</li>
<li>lesson 3:  45 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h3>ch 17: Supporting an Application  (total:  2:10)</h3>

<ul>
<li>lesson 1:  60 minutes</li>
<li>lesson 2:  60 minutes</li>
<li>review: 10 minutes</li>
</ul>

<h1>Totals:</h1>

<p>70-536 Foundations:  26:30
70-528 Web:  23:10
70-547 Designing:  23:30</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/08/mcpd-net-web-self-paced-training-kit-time-estimate-summary/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Making a symfony plug-in for visual theme and custom errors</title>
		<link>http://n8v.enteuxis.org/2009/06/making-a-symfony-plug-in-for-visual-theme-and-custom-errors/</link>
		<comments>http://n8v.enteuxis.org/2009/06/making-a-symfony-plug-in-for-visual-theme-and-custom-errors/#comments</comments>
		<pubDate>Fri, 26 Jun 2009 00:13:38 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=255</guid>
		<description><![CDATA[I manage a growing number of symfony-based Intranet apps that share a common look-and-feel.  I use the same stylesheet and images on them all, and it I am nervous every time I make Yet Another Copy of the same files, knowing that I&#8217;m duplicating them and causing trouble for myself.

Also, as I wrote in [...]]]></description>
			<content:encoded><![CDATA[<p>I manage a growing number of symfony-based Intranet apps that share a common look-and-feel.  I use the same stylesheet and images on them all, and it I am nervous every time I make Yet Another Copy of the same files, knowing that I&#8217;m duplicating them and causing trouble for myself.</p>

<p>Also, as I wrote in <a href="/2009/03/completely-custom-symfony-error-pages/">my post about custom error pages</a>, I have error pages set up for each, and I hate copying them.  So I have invested some time into building a plugin containing the visual assets and the customized error pages, so that it&#8217;s easier to keep them uniform across all the apps I work on, and so that it will be that much quicker to build new projects.</p>

<p>I don&#8217;t think anyone outside my company will want my plug-in, but these instructions will hopefully be useful for anyone who wants to do the same thing.</p>

<p><span id="more-255"></span></p>

<p>These instructions are for symfony 1.1 but they should apply equally to 1.0 and 1.2.</p>

<h2>Plugin organization</h2>

<p>Here are the files and directories in my plugin:</p>

<p><pre>plugins/myThemePlugin/
  config/
    view.yml
  modules/
    default/
      config/
        view.yml
      templates/
        disabledSuccess.php
        error404Success.php
  README
  web/
    css/
      mystyles.css
      myerrors.css
      mymain.css
    errors/
      error500.php
      unavailable.php
    images/
      my_swoop.jpg
      bg_sfTAlert.jpg
      bg_sfTLock.jpg
      bg_sfTMessage.jpg
      indicator.gif
      tall_gradient.jpg
</pre></p>

<h2>Using <code>svn:externals</code> to install the plugin in each symfony project</h2>

<p>I only want one copy of this thing, with version control, so I use svn:externals (for my other plugins too ).</p>

<p><pre>$ svn propget svn:externals plugins
myThemePlugin/        https://mysvnserver.com/svn/web/myThemePlugin
sfGuardPlugin/        http://svn.symfony-project.com/plugins/sfGuardPlugin/branches/1.1/
$ svn up
</pre></p>

<h2>Publishing the assets</h2>

<p>The <a href="http://www.symfony-project.org/book/1_2/17-Extending-Symfony#chapter_17_sub_anatomy_of_a_plug_in">chapter on plugins</a> in the <cite>The Definitive Guide to symfony</cite> explains:</p>

<blockquote>
  <p>Web assets (images, scripts, style sheets, etc.) are made available to the server. When you install a plug-in via the command line, symfony creates a symlink to the project <code>web/</code> directory if the system allows it, or copies the content of the module <code>web/</code> directory into the project one. If the plug-in is installed from an archive or a version control repository, you have to copy the plug-in <code>web/</code> directory by hand (as the <code>README</code> bundled with the plug-in should mention).</p>
</blockquote>

<p>As I showed above, I prefer to use <code>svn:externals</code> for my plugins, so this is a bit of a problem for me.  Also, I develop on Windows (with XAMPP and Cygwin), so the more elegant symlink solution is not an option.   Symfony 1.2 has a task called <code>plugin:publish_assets</code> that makes the copies, but that messes up my version control strategy. SO:  I am going to use <code>svn:externals</code> to get the web assets from my plugin too.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">svn</span> propset <span class="kw2">svn</span>:externals <span class="st0">&quot;myThemePlugin  https://my_svn_server/svn/web/myThemePlugin/web/&quot;</span> web
$ <span class="kw2">svn</span> propget <span class="kw2">svn</span>:externals web
    myThemePlugin  https:<span class="sy0">//</span>my_svn_server<span class="sy0">/</span><span class="kw2">svn</span><span class="sy0">/</span>web<span class="sy0">/</span>myThemePlugin<span class="sy0">/</span>web<span class="sy0">/</span>
$ <span class="kw2">svn</span> up</pre></div></div>


<p>This lets me keep the plugin in its own repository.  You could get a similar effect by just checking out the files, but it would clutter up the SVN for your main project.</p>

<p>The end result:  I have one copy of the web assets in the SVN repository, but they&#8217;re checked out twice into each project (once under <var>plugins/myThemePlugin/web</var> and once under <var>web/myThemePlugin</var>).</p>

<h2><var>view.yml</var> files</h2>

<p>Now the overall <var>view.yml</var> file in <var>plugins/myThemePlugin/config/</var> sets stylesheets for my whole project:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">default:
  stylesheets:    
    - /myThemePlugin/css/main: { position: last }
    - /myThemePlugin/css/bannerhealth: {position: last}
    - %SF_ADMIN_WEB_DIR%/css/main
    - %SF_CALENDAR_WEB_DIR%/skins/aqua/theme</pre></div></div>


<p>And I have another one to apply some additional stylesheets to my error pages:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">error404Success:
  metas:
    title:        404 Not Found
  stylesheets: 
    - /sf/sf_default/css/screen.css
    - /sf/sf_default/css/ie.css
    - /myThemePlugin/css/errors: {position: last}
&nbsp;
disabledSuccess:
  metas:
    title:        Temporarily Unavailable
  stylesheets: 
    - /sf/sf_default/css/screen.css
    - /sf/sf_default/css/ie.css
    - /myThemePlugin/css/errors: {position: last}</pre></div></div>


<h3>relative image paths in stylesheets and error pages</h3>

<p>I use relative paths in my stylesheets (served out of <var>myprojecturl/myThemePlugin/css/</var>) so they can find the images (<var>myprojecturl/myThemePlugin/images/</var>):</p>


<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw1">background-image</span><span class="sy0">:</span> <span class="kw2">url</span><span class="br0">&#40;</span><span class="co2">../images/tall_gradient.jpg</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>


<p>I&#8217;d do the same if my error templates (like <var>plugins/myThemePlugin/modules/default/templates/error404Success.php</var>) used images, but they don&#8217;t.</p>

<p>The pages in <var>plugins/myThemePlugin/web/errors</var> (which are installed via <code>svn:externals</code> now in <var>web/myThemePlugin/errors</var>) are used when things are so broken symfony can&#8217;t build template pages, so they have full HTML structure, including full stylesheet tags:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">&lt;?php</span> <span class="re0">$path</span> <span class="sy0">=</span> <span class="st_h">'..'</span><span class="sy0">;</span> <span class="sy1">?&gt;</span>
&nbsp;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/../sf/sf_default/css/screen.css&quot; /&gt;
&lt;!--[if lt IE 7.]&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/../sf/sf_default/css/ie.css&quot; /&gt;
&lt;![endif]--&gt;
&nbsp;
&nbsp;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/css/main.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/css/bannerhealth.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$path</span> <span class="sy1">?&gt;</span>/css/errors.css&quot; /&gt;</pre></div></div>


<h2>Apache error page configuration</h2>

<p>Finally, I tell Apache to use my customized error pages for errors in this project.</p>


<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  &lt;<span class="kw3">Directory</span> <span class="st0">&quot;/path/to/myproject/web&quot;</span>&gt;
        <span class="kw1">ErrorDocument</span> <span class="nu0">404</span> /myproject/default/error404
	<span class="kw1">ErrorDocument</span> <span class="nu0">500</span> /myproject/bhThemePlugin/errors/error500.php
  &lt;/<span class="kw3">Directory</span>&gt;</pre></div></div>


<p>There we go!   Now I have a lot less to do each time I make a new app; all the pretty stuff is in my plugin, and there aren&#8217;t any surprisingly brown symfony pages to throw off any users.</p>

<p>What do you think?  Any errors or ommissions or problems?</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/06/making-a-symfony-plug-in-for-visual-theme-and-custom-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More Secure AND More Convenient: Secure Shell keys and agents everywhere you go</title>
		<link>http://n8v.enteuxis.org/2009/05/more-secure-and-more-convenient-secure-shell-keys-and-agents-everywhere-you-go/</link>
		<comments>http://n8v.enteuxis.org/2009/05/more-secure-and-more-convenient-secure-shell-keys-and-agents-everywhere-you-go/#comments</comments>
		<pubDate>Fri, 29 May 2009 00:50:50 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[auth]]></category>
		<category><![CDATA[Cygwin]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[public key]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=38</guid>
		<description><![CDATA[As security increases, convenience tends to decrease.  But in this case we gain some of both.

CONCEPTS

Problem 1: Brute force SSH attackers

I recently made a Linux machine accessible by port 22 from the Internet, so I could remotely administer it with SSH.  Within a day or two, there were hosts from all over the [...]]]></description>
			<content:encoded><![CDATA[<p>As security increases, convenience tends to decrease.  But in this case we gain some of both.</p>

<h2>CONCEPTS</h2>

<h3>Problem 1: Brute force SSH attackers</h3>

<p>I recently made a Linux machine accessible by port 22 from the Internet, so I could remotely administer it with SSH.  Within a day or two, there were hosts from all over the Internet trying to log in using random usernames (&#8216;root&#8217;, &#8216;dave&#8217;, &#8216;mysql&#8217;, &#8216;neo&#8217;) and random passwords.</p>

<h3>Problem 2: Weak system passwords</h3>

<p>System passwords are becoming easier to guess by brute force every time a new processor comes out.  It doesn&#8217;t matter how complicated your alphabet soup is, it&#8217;s just not long enough, or won&#8217;t be long enough eventually.  The bad guys also have botnets full of machines and all the time in the world.</p>

<h3>Working around problems 1 and 2: Key authentication</h3>

<p>An SSH key is complex (random) and much, much longer than your password (<a href="http://en.wikipedia.org/wiki/Public-key_cryptography">see Wikipedia for more details about how public-key cryptography works</a>).  You store the private part of your key securely on your client machine, and tell the server to trust only the public key that goes with it.  BUT, you should really use a nice, long, complex passphrase to lock up your private key so that someone who gains access to it can&#8217;t get free access to all your servers, which leads to</p>

<h3>Problem 3:  I&#8217;m too lazy to unlock my inconvenient SSH key all the time</h3>

<p>I log in to different machines all the time, from a bunch of different workstations.  But, I have a long passphrase on my SSH key.  Too long to type every time, especially if I&#8217;m just looking at something or transferring a file or two.</p>

<h3>Solution to problem 3:  A key agent</h3>

<p>An SSH key agent lets you unlock your key and load it into memory once, and then automatically uses it to get you in to all your servers.  SUPER convenient.</p>

<h3>Problem 4:  It&#8217;s confusing</h3>

<p>I tried to explain it to a friend recently and found nowhere on the internets that explained it all in one place.</p>

<p>Coming up:  detailed instructions for getting started with SSH keys and using a key agent on Mac OS X (command line), Windows (PuTTY and Cygwin commandline ssh), and Linux/Unix (command line).</p>

<p><span id="more-38"></span></p>

<h2>HOW TO START USING SSH KEYS</h2>

<h3>References:</h3>

<ul>
<li><a href="http://www.tartarus.org/~simon/puttydoc/Chapter8.html#pubkey">PuTTY manual chapter 8</a>
and <a href="http://www.tartarus.org/~simon/puttydoc/Chapter9.html">chapter 9</a></li>
<li>section 2.4 of the <a href="http://www.snailbook.com/">O&#8217;Reilly SSH book by Barrett/Silverman</a></li>
<li><code>man <a href="http://linux.die.net/man/5/ssh_config">ssh_config</a></code></li>
<li><code>man <a href="http://linux.die.net/man/1/ssh-agent">ssh-agent</a></code></li>
</ul>

<h3>Generate your key with a command-line (Open)SSH client (Cygwin, Mac OS X, Linux)</h3>

<p>I&#8217;m going to start with this client, because the command-line OpenSSH is the common denominator on all the OSes I use.</p>

<ol>
<li><p>Write down a nice long, complex, memorable passphrase that you&#8217;re capable of typing reliably, and store it in a safe place.  You probably won&#8217;t need it every day (unless you reboot a lot), so make sure you can remember and type it.  Security expert Bruce Schneier suggests <a href="http://www.schneier.com/blog/archives/2005/06/write_down_your.html">a scrap of paper in your wallet is a pretty good place</a>.</p></li>
<li><p>Generate a private key with <var>ssh-keygen </var>from your client machine&#8217;s command line:</p></li>
</ol>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">ssh-keygen</span> <span class="re5">-t</span> rsa
Generating public<span class="sy0">/</span>private rsa key pair.
Enter <span class="kw2">file</span> <span class="kw1">in</span> <span class="kw2">which</span> to save the key <span class="br0">&#40;</span><span class="sy0">/</span>home<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa<span class="br0">&#41;</span>:
Enter passphrase <span class="br0">&#40;</span>empty <span class="kw1">for</span> no passphrase<span class="br0">&#41;</span>:     <span class="co0"># use yours from step 1</span>
Enter same passphrase again:
Your identification has been saved <span class="kw1">in</span> <span class="sy0">/</span>home<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa.
Your public key has been saved <span class="kw1">in</span> <span class="sy0">/</span>home<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa.pub.
The key fingerprint is:
9a:<span class="nu0">89</span>:9c:6b:<span class="nu0">87</span>:a7:e8:<span class="nu0">93</span>:9a:f5:f7:<span class="nu0">35</span>:bf:<span class="nu0">23</span>:<span class="nu0">87</span>:c6 myusername<span class="sy0">@</span>myhostname</pre></div></div>


<ol>
<li>The file permissions of your new <var>.ssh</var> directory and the files in it (except maybe your public key) should be very restrictive, allowing only you to read them.  But just in case, reset them restrictively:</li>
</ol>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">chmod</span> <span class="nu0">700</span> ~<span class="sy0">/</span>.ssh
<span class="kw2">chmod</span> <span class="nu0">600</span> ~<span class="sy0">/</span>.ssh<span class="sy0">/*</span>
<span class="kw2">chmod</span> <span class="nu0">644</span> ~<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa.pub</pre></div></div>


<ol>
<li>You need to append your public key to <var>~/.ssh/authorized_keys</var> on each of your servers:

<ul>
<li>if you don&#8217;t have an authorized_keys file in your <var>~/.ssh</var> directory, just copy your public key to it on each server:</li>
</ul></li>
</ol>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">scp</span> <span class="re5">-r</span> ~<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa.pub  myserver:.ssh<span class="sy0">/</span>authorized_keys</pre></div></div>


<ul>
<li>if you already have one, you&#8217;ll need to append your key to it.  Use a text editor and paste, copy and paste, or, courtesy of <a href="http://codesnippets.joyent.com/posts/show/906">CodeSnippets</a>,</li>
</ul>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">cat</span> .ssh<span class="sy0">/</span>id_dsa.pub <span class="sy0">|</span> <span class="kw2">ssh</span> user<span class="sy0">@</span>domain.tld <span class="st_h">'cat &gt;&gt; .ssh/authorized_keys'</span></pre></div></div>


<ol>
<li>Test and make sure it works!  When you ssh to the server, it should prompt you for your passphrase to unlock your private key, and then you should successfully connect.  Using the -d flag to ssh gives you verbose debugging information which is usually useful.</li>
</ol>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">ssh</span> <span class="re5">-v</span> myserver
... <span class="co0"># copious debug information about which keys or </span>
... <span class="co0"># authentication methods ssh is trying ]</span>
Enter passphrase <span class="kw1">for</span> key <span class="st_h">'~/.ssh/id_rsa'</span>:
... <span class="co0"># here's where you type your passphrase correctly</span>
... <span class="co0"># more debugging</span>
debug1: Entering interactive session.
Last <span class="kw2">login</span>: Thu May <span class="nu0">21</span> <span class="nu0">14</span>:<span class="nu0">30</span>:<span class="nu0">31</span> <span class="nu0">2009</span> from 10.0.0.2</pre></div></div>


<ol>
<li><p>I like to turn on agent forwarding by adding this line to <var>~/.ssh/config</var> file on each server.  This allows you to ssh from server A to another server B that trusts your key, using the agent on your client machine to pass your key through.
ForwardAgent yes</p></li>
<li><p>If all the users on the server will be using keys from now on, it&#8217;s a good idea to turn off password authentication for the whole server, in sshd_config, which is usually located in <var>/etc/</var>:
PasswordAuthentication no
Unfortunately, I can&#8217;t figure out how to lock one account on the server from using password authentication.  You can put that line in your <var>~/.ssh/config</var> file, but it only affects your use of ssh <em>from</em> that account, not <em>to</em> it.</p></li>
</ol>

<h3>Or, generate your key with PuTTY on Windows:</h3>

<p>PuTTY is rock-solid terminal and SSH software for Windows.  I usually generate my key with the command-line OpenSSH tools and then import it to PuTTY, but here&#8217;s how you do it the other way around:</p>

<ol>
<li><p>Install the <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">latest version of the whole PuTTY package</a>.  At the time of this writing, the PuTTY author&#8217;s site has been inaccessible for a while, but there are <a href="http://the.earth.li/~sgtatham/putty/0.60/x86/">mirrors available</a> for downloading the software.</p></li>
<li><p>Generate an RSA key with puttygen.exe, using a good passphrase (see instructions in the <a href="http://www.tartarus.org/~simon/puttydoc/Chapter8.html#pubkey">PuTTY manual chapter 8</a>)
<div id="attachment_233" class="wp-caption alignnone" style="width: 493px"><img src="http://n8v.enteuxis.org/wp-content/uploads/2009/05/puttygen.png" alt="Generating a key with puttygen.exe" title="puttygen" width="483" height="471" class="size-full wp-image-233" /><p class="wp-caption-text">Generating a key with puttygen.exe</p></div></p></li>
<li><p>Save the private key somewhere using the &#8216;Save private key&#8217; button, like maybe in <var>C:\Documents and Settings\<samp>yourusername</samp>&#92;.ssh\puttyprivkey</var> to be compatible with command-line SSH tools.  Save the public key somewhere too (though you will paste it, below).</p></li>
<li><p>Make the file permissions of that directory and the files in it very restrictive (only you should have access).</p></li>
<li><p>On one server, edit <var>.ssh/authorized_keys</var> in your home directory (creating it if it doesn&#8217;t exist yet), and paste your public key from puttygen in there</p></li>
<li><p>Test that it works!  Tell PuTTY to try key authentication instead of password authentication by setting your private key under Connection->SSH->Auth in the connection settings:
<div id="attachment_232" class="wp-caption alignnone" style="width: 466px"><img src="http://n8v.enteuxis.org/wp-content/uploads/2009/05/putty_ssh_key_settings.png" alt="Tell PuTTY to use your key" title="putty_ssh_key_settings" width="456" height="442" class="size-full wp-image-232" /><p class="wp-caption-text">Tell PuTTY to use your key</p></div></p></li>
<li><p>Copy the <var>authorized_keys</var> file and/or the whole <var>.ssh</var> directory to each other server.  Eg on the first server, <code>scp -r .ssh myotherserver:</code></p></li>
<li><p>Turn on agent forwarding (and &#8220;try to use Pageant&#8221;&#8230; see screenshot above) for each ssh session config in PuTTY in the Connection-&gt;SSH-&gt;Auth pane (this lets you ssh from server A to another server using the agent on your client machine)</p></li>
<li><p>Put your username in the &#8220;Auto-login username&#8221; field under Connection-&gt;Data for each saved PuTTY session:
<div id="attachment_249" class="wp-caption alignnone" style="width: 466px"><img src="http://n8v.enteuxis.org/wp-content/uploads/2009/05/putty_username.png" alt="Don&#039;t forget to fill in the Auto-login username field for each saved PuTTY session." title="putty_username" width="456" height="442" class="size-full wp-image-249" /><p class="wp-caption-text">Don't forget to fill in the Auto-login username field for each saved PuTTY session.</p></div></p></li>
</ol>

<h4>Using your PuTTY key with command-line ssh client (Cygwin, Mac OS X, Linux):</h4>

<p>If you want to use the key you just generated with puttygen.exe with
another ssh client (eg cygwin commandline <var>ssh</var>), export your
private key from puttygen and store it in your <var>.ssh</var> dir
(ssh looks by default for <var>.ssh/id_rsa</var> but these
instructions let you specify another name), and put these lines in
your <var>.ssh/config</var> file:</p>

<pre><code>ForwardAgent yes
IdentityFile ~/.ssh/id_rsa_putty_priv.openssh
</code></pre>

<p>( i.e., the filename of your exported private key )</p>

<h4>To change your ssh key password</h4>

<p>Load it in <var>puttygen</var> and change the password, save and
export it for your other ssh client(s) if necessary</p>

<h4>Using a different key from home or another machine or whatever</h4>

<p>You can copy your private key to several machines, or you can generate
a new key on each and append the public key to the
<var>.ssh/authorized_keys</var> file on the server. Think about how
much you want to expose/replace if something gets compromised.</p>

<p>In my case, I use one private key on all my client computers at work, one
on my home computers, and one on my Palm handheld. That way if one of
my client computers is lost, stolen or compromised, I can disallow
that key but keep the others.</p>

<h2>USE A KEY AGENT TO KEEP YOUR KEYS HANDY</h2>

<p>So far, we&#8217;ve made SSH more secure, but my key passphrase is at least as much of a pain as using my password &#8212; in fact, more so because it&#8217;s about twice as long.</p>

<p>Using an SSH Key Agent offers a killer mix of security <em>and</em> convenience.  When you open the agent and load your keys, you can unlock them and they&#8217;re held unlocked in memory.  This lets you open connections all day without having to type your password or passphrase.  <strong>NOTE WELL</strong>, lock your machine when it is unattended if you have an agent running; otherwise anyone who walks up to it can conceivably log in to any of the servers you&#8217;ve configured to trust your key.</p>

<h3>To use PuTTY&#8217;s agent &#8220;Pageant&#8221; on Windows:</h3>

<ol>
<li>Launch <var>pageant.exe</var>, PuTTY&#8217;s ssh agent, right-click it in the system tray, and add your private key.</li>
</ol>

<p>Now you can log into all your servers conveniently and get from server to server using agent forwarding.</p>

<p>You may want to convince pageant.exe to run at login.  See <a href="http://www.tartarus.org/~simon/puttydoc/Chapter9.html">Chapter 9 of the PuTTY manual</a>.</p>

<p>I just made a shortcut to pageant and edited the Target to load the key and launch PuTTY at startup thusly:
<code>
"C:\Program Files\putty\pageant.exe" "C:\Documents and Settings\myusername&#46;ssh\puttyprivkey.ppk" -c "C:\Program Files\PuTTY\putty.exe"</code></p>

<h3>To run an agent with the command-line OpenSSH client:</h3>

<p>This applies to Linux, Mac OS X, and Cygwin.</p>

<p>Basically, add this line to your <var>.profile</var> file in your home directory, to start the agent whenever you open a shell:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw3">eval</span> <span class="sy0">`</span><span class="kw2">ssh-agent</span> -s<span class="sy0">`</span></pre></div></div>


<p>Then, before you ssh to anything in that terminal, use the <code>ssh-add</code> command (if your private key in openssh format is named <var>.ssh/id_rsa</var>) or <code>ssh-add ~/.ssh/puttyprivkey.openssh</code> if you&#8217;ve got a weirdly named one you made with puttygen.exe, above.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">ssh-add</span>
Enter passphrase <span class="kw1">for</span> <span class="sy0">/</span>cygdrive<span class="sy0">/</span>c<span class="sy0">/</span>Documents and Settings<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa:
Identity added: <span class="sy0">/</span>cygdrive<span class="sy0">/</span>c<span class="sy0">/</span>Documents and Settings<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa <span class="br0">&#40;</span><span class="sy0">/</span>cygdrive<span class="sy0">/</span>c<span class="sy0">/</span>Documents and Settings<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa<span class="br0">&#41;</span></pre></div></div>


<p><code>ssh-add -l</code> (ell) shows which keys the agent is currently holding.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">ssh-add</span> <span class="re5">-l</span>
9a:<span class="nu0">89</span>:9c:6b:<span class="nu0">87</span>:a7:e8:<span class="nu0">93</span>:9a:f5:f7:<span class="nu0">35</span>:bf:<span class="nu0">23</span>:<span class="nu0">87</span>:c6 <span class="sy0">/</span>cygdrive<span class="sy0">/</span>c<span class="sy0">/</span>Documents and Settings<span class="sy0">/</span>myusername<span class="sy0">/</span>.ssh<span class="sy0">/</span>id_rsa <span class="br0">&#40;</span>RSA<span class="br0">&#41;</span></pre></div></div>


<h3>Making it nicer in with <code>keychain</code></h3>

<p>The <a href="http://www.gentoo.org/proj/en/keychain/">keychain
utility</a> you can get with Cygwin (and some Linuxes) is also nice.
I put this line in my <var>.bashrc</var> so that every Cygwin shell
either starts the ssh agent or connects to the already running one.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw3">eval</span> <span class="sy0">`</span>keychain <span class="re5">--eval</span> <span class="re5">-q</span> <span class="re5">-Q</span> --noask<span class="sy0">`</span></pre></div></div>


<p>Then I can use <var>ssh-add</var> (see above) when I want to load my keyring, and
all my open Cygwin shells get it, until I log out or restart Windows.</p>

<h3>Running an agent on Mac OS X</h3>

<p>In Leopard (Mac OS X 10.5, released in October 2007), the <a href="http://www.dribin.org/dave/blog/archives/2007/11/28/ssh_agent_leopard/">SSH Agent is integrated into the OS</a>, so if you&#8217;ve generated your keys with <code>ssh-keygen</code> as above and they live in <code>~/.ssh/id_rsa</code> and <code>id_rsa.pub</code>, you will get prompted to unlock your key the first time you try to <code>ssh</code> or <code>scp</code> anywhere:</p>

<div id="attachment_253" class="wp-caption alignnone" style="width: 591px"><img src="http://n8v.enteuxis.org/wp-content/uploads/2009/05/leopard-ssh-agent.png" alt="This dialog box prompts you to unlock your key and/or start the agent." title="leopard-ssh-agent" width="581" height="414" class="size-full wp-image-253" /><p class="wp-caption-text">This dialog box prompts you to unlock your key and/or start the agent.</p></div>

<p>The &#8220;Remember password in my keychain&#8221; checkbox makes it keep an ssh agent running.  It works great.</p>

<p>For older versions of Mac OS, you want <a href="http://www.sshkeychain.org/download.php">SSHKeychain</a>.  It also works with the Apple Keychain, to remember your key&#8217;s passphrase.</p>

<p>Both solutions work seamlessly for all the OpenSSH tools (ssh, sftp, scp, etc) in all your terminals.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/05/more-secure-and-more-convenient-secure-shell-keys-and-agents-everywhere-you-go/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wordpress plugin to make code samples prettier</title>
		<link>http://n8v.enteuxis.org/2009/03/wordpress-plugin-to-make-code-samples-prettier/</link>
		<comments>http://n8v.enteuxis.org/2009/03/wordpress-plugin-to-make-code-samples-prettier/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 00:24:52 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Giving back]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[syntax]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wp-syntax]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=215</guid>
		<description><![CDATA[I&#8217;ve always had a weakness for &#8220;preferences&#8221;.  I spent hours going through all the available preference panes on the first Mac I had access to (an SE II I think, ca. 1989), tweaking this and that to get it to look as &#8220;customized&#8221; as possible.  Hours setting up font and styles on school [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always had a weakness for &#8220;preferences&#8221;.  I spent hours going through all the available preference panes on the first Mac I had access to (an <var>SE II</var> I think, ca. 1989), tweaking this and that to get it to look as &#8220;customized&#8221; as possible.  Hours setting up font and styles on school assignments, days banging on my Emacs config to be more like I want.</p>

<p>So it&#8217;s been secretly irking me for a while that although I installed the very nice <a href="http://wordpress.org/extend/plugins/wp-syntax/">WP-Syntax code highlighting plugin </a>for this WordPress blog, it was hard to get it to display things in reverse-video like I prefer for all my terminal and text editor windows, and like I love in <a href="http://www.symfony-project.org/book/">the online Symfony documentation</a>.  It&#8217;s just nicer on the eyes, you know?  Digging in, I found the <a href="http://qbnz.com/highlighter/">GeSHI syntax highlighter</a> to be impressive in scope but scary in its inline-style-generating detail.</p>

<p>So today, to solve the problem for more than just me, I published <a href="http://wordpress.org/extend/plugins/wp-syntax-hacktify/">my very first WordPress plugin, wp-syntax-hacktify</a>.  Very educational!  I like the plugin system at wordpress.org.</p>

<p>The plugin tells GeSHI to use stylesheets instead and provides a <a href="http://svn.wp-plugins.org/wp-syntax-hacktify/trunk/hacktified.css">slightly more commented/documented stylesheet</a> as an example for if you&#8217;d like to override it with your own color scheme.</p>

<p>So now my code samples can be all nicer and stuff, like this:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  <span class="co4">/**
   * Print a string to the log using 'debug' level.  For printf-style
   * debugging.
   *
   * @param      string $m      The string to log
   * @return     nothing
   */</span>
  <span class="kw2">public</span> <a href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> debug <span class="br0">&#40;</span><span class="re0">$m</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>sfConfig<span class="sy0">::</span><span class="me2">has</span><span class="br0">&#40;</span><span class="st_h">'sf_logging_enabled'</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_logging_enabled'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$logger</span> <span class="sy0">=</span> sfContext<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getLogger</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
          <span class="re0">$logger</span><span class="sy0">-&gt;</span><span class="me1">debug</span><span class="br0">&#40;</span><span class="re0">$m</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
      <span class="br0">&#125;</span>
    <span class="kw1">elseif</span> <span class="br0">&#40;</span>sfConfig<span class="sy0">::</span><span class="me2">has</span><span class="br0">&#40;</span><span class="st_h">'bhLDAP_echo_debugging'</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'bhLDAP_echo_debugging'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;# <span class="es4">$m</span><span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="kw1">else</span>
      <span class="br0">&#123;</span>
<span class="co1">//      echo $m;</span>
      <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co4">/**
   * Dump a data structure to the log at the 'debug' level.  Uses
   * print_r() formatting.
   *
   * @param      mixed $v         The variable/data structure to dump
   * @param      string $label    An optional label to print in front of the dump
   * @return     nothing
   */</span>
  <span class="kw2">public</span> <a href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> debugDump <span class="br0">&#40;</span><span class="re0">$v</span><span class="sy0">,</span> <span class="re0">$label</span> <span class="sy0">=</span> <span class="st0">&quot;var dump&quot;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">self</span><span class="sy0">::</span><span class="me2">debug</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es4">$label</span>:  &quot;</span> <span class="sy0">.</span> <a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span><span class="re0">$v</span><span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>


<p>Now the code on my blog can look nice even if it&#8217;s terrifically hacky!</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/03/wordpress-plugin-to-make-code-samples-prettier/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Completely custom Symfony error pages</title>
		<link>http://n8v.enteuxis.org/2009/03/completely-custom-symfony-error-pages/</link>
		<comments>http://n8v.enteuxis.org/2009/03/completely-custom-symfony-error-pages/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 22:39:58 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=177</guid>
		<description><![CDATA[For every Symfony project I work on, I eventually want to get rid of the tasteful brown error pages with the Symfony logo on them and install my own, so the users don&#8217;t get weirded out and somehow start thinking &#8220;Symfony = error&#8221;.  Also, I&#8217;m probably overly optimistic, but it would be nice if [...]]]></description>
			<content:encoded><![CDATA[<p>For every Symfony project I work on, I eventually want to get rid of the tasteful brown error pages with the Symfony logo on them and install my own, so the users don&#8217;t get weirded out and somehow start thinking &#8220;Symfony = error&#8221;.  Also, I&#8217;m probably overly optimistic, but it would be nice if there was a valid email address on the error page so I could hear users complain.</p>

<p><a href="http://www.symfony-project.org/book/1_1/19-Mastering-Symfony-s-Configuration-Files#chapter_19_sub_default_modules_and_actions">The documentation</a> is good, but I want a simpler recipe that also accounts for all the forseeable errors, even those that don&#8217;t get to Symfony.  Some details vary by version, but in short, for symfony 1.1:
<span id="more-177"></span></p>

<h3>Test URLs</h3>

<p>We want to ultimately make sure that these URLs behave the right way:</p>

<h4>Normal errors (must have)&#8211; 404 Not Found and 500 Server Error</h4>

<table cellpadding="3">
<tr style="background: rgb(218, 231, 180);"><td>
<var>http://<samp>localhost/myapp</samp>/default/error404</var>
</td><td>
The &#8220;real&#8221; 404 page&#8230; it&#8217;s actually strangely &#8220;found&#8221; in this case.
</td></tr>

<tr><td>

http://<samp>localhost/myapp/mymodule/view</samp>/id/22222

</td><td>
A <code>forward404Unless</code> style forwarding should get the custom 404 page.  This is really the most likely case&#8211; if a user follows a link to an object another user has deleted, I want them to see the nice page.

</td></tr>



<tr style="background: rgb(218, 231, 180);"><td>
http://<samp>localhost/myapp/</samp>junk.php , or 

http://<samp>localhost/myapp/</samp>images/junk.gif

</td><td>
A request that Apache handles should display the custom 404 page too.
</td></tr>

<tr><td>

http://<samp>localhost/myapp</samp>/errors/error500.php

</td><td>
The &#8220;real&#8221; URL of the 500 error page should work.
</td></tr>

<tr style="background: rgb(218, 231, 180);"><td>

http://<samp>localhost/myapp</samp>/awfijwef/awfijawfo

</td><td>
Another real 404 error&#8211; Symfony forwards nonsensical module/action stuff to the custom 404 page.
</td></tr>


</table>

<p>I have seen error 500 pages countless times during app development, but I just could <strong>NOT</strong> reproduce one to test the 500 error page.  Any quick recipes for that, anyone?</p>

<h4>More esoteric error conditions&#8211; app unavailable/locked, module disabled</h4>

<table cellpadding="3">
<tr><td>
<var>http://localhost/myapp/errors/unavailable.php</var>
</td><td>
The &#8220;unavailable&#8221; page for when a whole symfony app is locked with <kbd>symfony project:disable <samp>app env</samp></kbd>*, or while the cache is being cleared.
</td></tr>


<tr style="background: rgb(218, 231, 180);"><td>
any application URL after I run <kbd>symfony project:disable</kbd> and I have the <code>check_lock</code> setting on*
</td><td>
should go to the &#8216;unavailable&#8217; page (unavailable.php)
</td></tr>

<tr><td>
<var>http://localhost/myapp/default/disabled</var>
</td><td>
The real &#8220;I&#8217;m disabled&#8221; page for when a module is locked with <kbd></kbd> in the <a href="http://www.symfony-project.org/book/1_1/06-Inside-the-Controller-Layer#chapter_06_module_configuration">module&#8217;s config file</a>, e.g. <var>apps/frontend/modules/<samp>mymodule</samp>/config/module.yml</var>
</td></tr>

<tr style="background: rgb(218, 231, 180);"><td>
http://<samp>localhost/myapp/</samp>mymodule/myaction , when I&#8217;ve explicitly disabled the module by putting this in <var>apps/frontend/mymodule/config/module.yml</var>:
<pre>
all:
  enabled:     false
</pre>
</td><td>
The disabled page (above)
</td></tr>


</table>

<h3>Steps</h3>

<ol>

    <li>manually create a few files for the <var>default</var> module.  <strong>DO NOT</strong> use <code>symfony generate:module</code> because you only want to override a small bit of the built-in <var>default</var> module (found in <var>/path/to/symfony/lib/controller/default/templates/</var>* incidentally, if you ever want to see what you&#8217;re overriding).


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">mkdir</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default
$ <span class="kw2">mkdir</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>config
$ <span class="kw2">mkdir</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>templates
$ <span class="kw2">touch</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>config<span class="sy0">/</span>view.yml
$ <span class="kw2">touch</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>templates<span class="sy0">/</span>error404Success.php
$ <span class="kw2">touch</span> apps<span class="sy0">/</span>frontend<span class="sy0">/</span>modules<span class="sy0">/</span>default<span class="sy0">/</span>templates<span class="sy0">/</span>disabledSuccess.php</pre></div></div>



</li>

    <li>Edit the templates I just made&#8211; remember, the content for these goes inside your sitewide <var>layout.php</var>.

I started out by copying the default templates in <var>lib/controller/default/templates/</var> from my Symfony distribution.
</li>
    <li>create mostly static pages for <var>web/errors/error500.php</var> and <var>unavailable.php</var>***  They won&#8217;t be wrapped in layout.php so they need to have the full page structure, and basically no symfony-involving PHP code (like helpers, too bad), though I do use a bit of really basic stuff, like including the URL in my mailto form on the 500 page:


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  &lt;dl class=&quot;sfTMessageInfo&quot;&gt;
    &lt;dt&gt;Something is terribly broken.&lt;/dt&gt;
    &lt;dd&gt;
	  &lt;p&gt;
Please 
&lt;a href=&quot;mailto:webmaster@mycompany.com?subject=500 error at http://
<span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'SERVER_NAME'</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st_h">'/'</span><span class="sy0">.</span> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'REQUEST_URI'</span><span class="br0">&#93;</span>  <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> 
<span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/array_key_exists"><span class="kw3">array_key_exists</span></a><span class="br0">&#40;</span><span class="st_h">'HTTP_REFERER'</span><span class="sy0">,</span> <span class="re0">$_SERVER</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
  <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;&amp;body=Referrer: &quot;</span><span class="sy0">.</span><span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'HTTP_REFERER'</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
 <span class="sy1">?&gt;</span>&quot;&gt;
e-mail us at webmaster@mycompany.com&lt;/a&gt; and let us know what you were doing when this error occurred. We will fix it as soon as possible.
&lt;/p&gt;
	  &lt;p&gt;
   If you have an urgent problem, please call the Support Desk at XXXX.
&lt;/p&gt;
	  &lt;p&gt;
   You may also find the &lt;a href=&quot;/README.html&quot;&gt;documentation&lt;/a&gt; useful.
&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;</pre></div></div>



</li>

    <li>Include my stylesheets, in <var>view.yml</var>:

<pre>
error404Success:
  metas:
    title:        ED Log 404 Not Found
  stylesheets:
    - -*
    - mystyles1: { position: last }
    - mystyles2: {position: last}
    - /sf/sf_default/css/screen.css
    - /sf/sf_default/css/ie.css
    - errors: {position: last}
</pre>
(and the same thing for <code>disabledSuccess:</code>)

My <var>web/css/errors.css</var>  overrides some of the default symfony error page styles (compare <var>web/sf/sf_default/css/screen.css</var> in your symfony distribution) to make them less brown, but I keep the general thing.
</li>

    <li>If your application has security on by default, make sure to un-secure the error pages so people can see them without logging in.  Add these above the <code>default</code> rule in <var>apps/frontend/config/security.yml</var>:

<pre>
error404:
  is_secure: off

disabled:
  is_secure: off
</pre>
</li>


    <li>Tell Apache where to find total 500 errors and 404 errors that don&#8217;t make it to symfony (like anything that doesn&#8217;t get to a front controller, like a misspelled controller or image name):


<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">  &lt;<span class="kw3">Directory</span> <span class="st0">&quot;/var/www/my_sf_app/web&quot;</span>&gt;
        <span class="kw1">ErrorDocument</span> <span class="nu0">404</span> /default/error404
	<span class="kw1">ErrorDocument</span> <span class="nu0">500</span> /errors/error500.php
  &lt;/<span class="kw3">Directory</span>&gt;</pre></div></div>



</li>

<li>Hrm, the table of URLs above sounds like a good test script&#8230; <strong>BUT</strong>, it resists scripting because most of the error URLs are outside symfony, so you don&#8217;t get the custom error pages when going to an actual error with sfTestBrowser, or even a regular sfBrowser, because instead you get fancy exception stuff.  

So, here&#8217;s a pretty lame test script I put in <var>test/functional/frontend/customErrors.php</var> that tests the easiest cases, but it&#8217;s not hard to manually try the others with a browser.  I welcome suggestions for improvement!


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">&nbsp;
<span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw1">include</span><span class="br0">&#40;</span><a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../../bootstrap/functional.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$e404_regexp</span> <span class="sy0">=</span> <span class="st0">&quot;webmaster@mycompany&quot;</span><span class="sy0">;</span>
<span class="re0">$disabled_regexp</span> <span class="sy0">=</span> <span class="st0">&quot;xXXXX&quot;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// create a new test browser</span>
<span class="re0">$browser</span> <span class="sy0">=</span> <span class="kw2">new</span> sfTestBrowser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="coMULTI">/* http://localhost/myapp/default/error404	 
The &quot;real&quot; 404 page */</span>
&nbsp;
<span class="re0">$browser</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'/default/error404'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">404</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'module'</span><span class="sy0">,</span> <span class="st_h">'default'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'action'</span><span class="sy0">,</span> <span class="st_h">'error404'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">checkResponseElement</span><span class="br0">&#40;</span><span class="st_h">'body'</span><span class="sy0">,</span> <span class="st0">&quot;/<span class="es4">$e404_regexp</span>/&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp;
<span class="coMULTI">/* http://localhost/myapp/default/disabled	 
The &quot;unavailable&quot; page for when symfony is locked with symfony project:disable */</span>
&nbsp;
<span class="re0">$browser</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'/default/disabled'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'module'</span><span class="sy0">,</span> <span class="st_h">'default'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">isRequestParameter</span><span class="br0">&#40;</span><span class="st_h">'action'</span><span class="sy0">,</span> <span class="st_h">'disabled'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">checkResponseElement</span><span class="br0">&#40;</span><span class="st_h">'body'</span><span class="sy0">,</span> <span class="st0">&quot;/<span class="es4">$disabled_regexp</span>/&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>




And a few passing tests is better than none, right?

<pre>
$ <kbd>php ./symfony test:functional frontend customError</kbd>
# get /default/error404
ok 1 - status code is 404
ok 2 - request parameter module is default
ok 3 - request parameter action is error404
ok 4 - response selector body matches regex /webmaster@mycompany/
# get /default/disabled
ok 5 - status code is 200
ok 6 - request parameter module is default
ok 7 - request parameter action is disabled
ok 8 - response selector body matches regex /xXXXX/
1..8
 Looks like everything went fine.
</pre>
</li>

</ol>

<p>Sheesh, it&#8217;s still a little too involved for such a small benefit.  If anyone has any ideas on how to streamline this procedure, let me know!  Maybe it could be a plugin or an enhancement to symfony?</p>

<ul>
<li>Disabling projects only works if the <a href="http://www.symfony-project.org/book/1_1/19-Mastering-Symfony-s-Configuration-Files#chapter_19_sub_default_modules_and_actions"><code>check_lock</code>  option</a> is enabled in e.g. <var>apps/frontend/config/settings.yml</var></li>
</ul>

<p>** Symfony 1.0 default templates are found in <var>&#8230;/symfony/data/modules/default/templates/</var> and include an &#8216;unavailable&#8217; template in addition to &#8216;disabled&#8217;.  Symfony 1.2 templates are in the same place as in 1.1.</p>

<p>*** Symfony 1.2 wants its 500 error page in <var>config/error/error.html.php</var></p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/03/completely-custom-symfony-error-pages/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Blorgbeard is my hero</title>
		<link>http://n8v.enteuxis.org/2009/02/blorgbeard-is-my-hero/</link>
		<comments>http://n8v.enteuxis.org/2009/02/blorgbeard-is-my-hero/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 19:37:20 +0000</pubDate>
		<dc:creator>nathan</dc:creator>
				<category><![CDATA[Figuring IT Out]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://n8v.enteuxis.org/?p=174</guid>
		<description><![CDATA[Yay!  When the books and Microsoft TechNet and Google and the blogosphere and a good night of sleep and even my genius coworker left me stumped on a technical question, the Kiwi named Blorgbeard got me through.

Stack Overflow is my new favorite thing on the Internet.  Seriously, it&#8217;s even better than Lolcats .
]]></description>
			<content:encoded><![CDATA[<p>Yay!  When the books and Microsoft TechNet and Google and the blogosphere and a good night of sleep and even my genius coworker left me stumped on a technical question, the <a href="http://stackoverflow.com/users/369/blorgbeard">Kiwi named Blorgbeard </a><a href="http://stackoverflow.com/questions/592983/how-do-i-include-empty-rows-in-a-single-group-by-daydatefield-sql-query/593402#593402">got me through</a>.</p>

<p><a href="http://stackoverflow.com/">Stack Overflow</a> is my new favorite thing on the Internet.  Seriously, it&#8217;s even better than <a href="http://icanhascheezburger.com/">Lolcats </a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://n8v.enteuxis.org/2009/02/blorgbeard-is-my-hero/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
