<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/1.5.2" -->
<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/"
>

<channel>
	<title>Gary Court</title>
	<link>http://garycourt.com</link>
	<description></description>
	<pubDate>Tue, 27 Feb 2007 04:44:24 +0000</pubDate>
	<generator>http://wordpress.org/?v=1.5.2</generator>
	<language>en</language>

		<item>
		<title>Stream Transcoded Media To Your XBox 360 Using TVersity</title>
		<link>http://garycourt.com/blog/post/stream-transcoded-media-to-your-xbox-360-using-tversity/</link>
		<comments>http://garycourt.com/blog/post/stream-transcoded-media-to-your-xbox-360-using-tversity/#comments</comments>
		<pubDate>Tue, 27 Feb 2007 04:38:52 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Tutorial</category>
	<category>Windows</category>
		<guid>http://garycourt.com/blog/post/stream-transcoded-media-to-your-xbox-360-using-tversity/</guid>
		<description><![CDATA[	Oh XBox 360, how do I love the! Let me count thy ways &#8230; but watching downloaded movies is not one of them. 
	With the recent fall update for the XBox 360, Microsoft has opened you its Media Client to allow it to connect to third-party UPnP Media Servers. Which is awesome, except for the [...]]]></description>
			<content:encoded><![CDATA[	<p>Oh XBox 360, how do I love the! Let me count thy ways &#8230; but watching downloaded movies is not one of them. </p>
	<p>With the recent fall update for the XBox 360, Microsoft has opened you its Media Client to allow it to connect to third-party <acronym title="Universal Plug and Play">UPnP</acronym> Media Servers. Which is awesome, except for the fact that the XBox 360 only supports <acronym title="Windows Media Video">WMV</acronym> (and MPEG) encoded movies. I mean seriously, no &#8220;person&#8221; voluntarily uses your media formats Microsoft. And with the 360&#8217;s horsepower, there shouldn&#8217;t be a problem here to decode these things in software. What&#8217;s a gamer to do?</p>
	<p>Thankfully a group, with a little piece of software called <a href="http://tversity.com">TVersity</a>, recently added <a href="http://en.wikipedia.org/wiki/Transcoding">transcoding</a> capabilities and support for the XBox 360 Media Client to allow for transcoded videos to be streamed to the XBox 360 on demand. As the little man rejoices and struggles to get it all to work, I write a guide on what I needed to do to unlock this desirable capability.<br />
<a id="more-18"></a></p>
	<p><strong>Note:</strong> The programs and versions used in this guide are:</p>
	<ul>
	<li><a href="http://www.microsoft.com/windows/windowsmedia/player/11/default.aspx">Windows Media Player 11</a></li>
	<li><a href="http://www.free-codecs.com/download/K_Lite_Codec_Pack.htm">K-Lite Codec Pack 2.84 Full</a></li>
	<li><a href="http://tversity.com/download/">TVersity 0.9.9.2</a></li>
	<li>XBox 360 w/ Fall 2006 Update</li>
	</ul>
	<h4>Uninstall Everything</h4>
	<p>It is highly recommended that you reinstall <a href="http://www.microsoft.com/windows/windowsmedia/default.mspx">Windows Media Player</a>, even if you already have 11 installed. Don&#8217;t ask why, but many people who were having trouble have gotten it to work by reinstalling everything. To do this, go to <strong>Control Panel</strong> -> <strong>Add or Remove Programs</strong>. First, uninstall any programs that start with <em>&#8220;Windows Media&#8221;</em>. Secondly, go to the <em>&#8220;Add/Remove Windows Components&#8221;</em> tab and uncheck <em>&#8220;Windows Media Player&#8221;</em> (click Next to uninstall). I recommend restarting your computer once this is all done.</p>
	<p>One of the things that I have noticed in my testing is that TVersity is extremely picky in its <a href="http://en.wikipedia.org/wiki/Codec">codecs</a>. Therefore, (and this really isn&#8217;t optional) uninstall all exisiting codecs and codec packs from your system. Yes, that means <a href="http://www.divx.com/">DivX</a>, <a href="http://www.xvid.org/">Xvid</a>, <a href="http://en.wikipedia.org/wiki/Ffdshow">ffdshow</a>, and/or any packs that contains codecs. If you have no idea what a codec is, chances are you have never installed one. However, it is best to look for programs with the aforementioned names in case your or someone else has installed one.</p>
	<h4>Prerequisites</h4>
	<p>TVersity works best with <a href="http://www.microsoft.com/windows/windowsmedia/player/11/default.aspx">Windows Media Player 11</a> and Windows users can <a href="http://www.microsoft.com/windows/windowsmedia/download/AllDownloads.aspx">download</a> this program for free from Microsoft&#8217;s website. The install is fairly straight forward and shouldn&#8217;t need explanation. On a side note, <acronym title="Windows Media Player">WMP</acronym> has come a long ways since its earlier days and version 11 is a very well polished, fast media player. After having used <a href="http://www.winamp.com/">Winamp</a> my entire life, I was almost swayed to actually start using Microsoft&#8217;s latest media player. (Almost, being the important word here as nothing beats the old <a href="http://www.winamp.com/">Winamp</a>/<a href="http://www.videolan.org/vlc/">VLC</a> combo)</p>
	<p>Next, your going to need the proper codecs to decode your movies for transcoding. After playing with a couple codec packs, I have had the best success with the <a href="http://www.free-codecs.com/download/K_Lite_Codec_Pack.htm">K-Lite Codec Pack Full</a>. When installing this pack, during the installation customization phase, be sure to uncheck the first DivX and XviD checkboxes as TVersity prefers to use ffdshow to decode its videos. Since ffdshow already decodes these formats, its best to not install the seperate codecs. (Remember, TVersity is picky with its codecs. I was unable to get it to work with the official DivX and XviD codecs.)</p>
	<h4>Installation &#038; Setup</h4>
	<p>Next, <a href="http://tversity.com/download/">install the latest version of TVersity</a> from the <a href="http://tversity.com/">official website</a>. This is also very straight forward, but requires some setup before using.</p>
	<p>When the installation is done, stop the Media Server by going to <strong>All Programs</strong> -> <strong>TVsersity Media Server</strong> -> <strong>TVersity Tools</strong> -> <strong>Stop TVersity Media Server</strong>. Next, edit the file <strong>C:\Program Files\TVersity\Media Server\profiles.xml</strong> using notepad and find the line:</p>
	<pre>
        &lt;transcodetarget audio=&quot;audio/L16&quot; video=&quot;video/x-ms-wmv&quot; photo=&quot;image/jpeg&quot;
                         onlineAudio=&quot;audio/mpeg&quot; onlineVideo=&quot;video/x-ms-wmv&quot; onlinePhoto=&quot;image/jpeg&quot;/&gt;
</pre>
	<p>To the end of this tag, add <code> actualSizeMatchFileSize=&quot;true&quot;</code> to produce the following:</p>
	<pre>
        &lt;transcodetarget audio=&quot;audio/L16&quot; video=&quot;video/x-ms-wmv&quot; photo=&quot;image/jpeg&quot;
                         onlineAudio=&quot;audio/mpeg&quot; onlineVideo=&quot;video/x-ms-wmv&quot; onlinePhoto=&quot;image/jpeg&quot; actualSizeMatchFileSize=&quot;true&quot;/&gt;
</pre>
	<p>Restart the media server by redoing the previous instructions, except selecting <strong>Start TVersity Media Server</strong> instead.</p>
	<p>You can launch the TVersity frontend by the icon on your desktop or <strong>All Programs</strong> -> <strong>TVsersity Media Server</strong> -> <strong>TVsersity Media Server</strong>. From within this program, you can modify the TVersity trancode settings from the <strong>Settings</strong> tab on the main screen, and clicking on <strong>Transcoder</strong> on the left. For a typical setup where you have a moderately fast computer and your XBox 360 is connected via a network cable, I would recommend the following settings:</p>
	<ul>
	<li>Select: Transcode only when needed</li>
	<li>Uncheck: Decrease the bitrate if it is too high for my network</li>
	<li>Select: Optimize: Quality</li>
	<li>Select: Connection Speed: Wired (100 mbps)</li>
	<li>Select: Connection Quality: Excellent</li>
	<li>Select: Compression: Minimum</li>
	<li>Enter: Video Resolution: 1280 x 720</li>
	<li>Uncheck: Decode the media as fast as possible without taking into account its bitrate</li>
	</ul>
	<p>Click <strong>save</strong> in the bottom right to save your changes.</p>
	<p>Don&#8217;t forget to add some test content - I would recommend adding DivX, XviD, MPEG 2 &#038; 4, and WMV encoded videos to make sure everything transcodes properly. TVersity also supports MP3s and <a href="http://www.shoutcast.com/">SHOUTcast</a> streams, which are nice to stream while gaming.</p>
	<h4>Connect the 360</h4>
	<p>To connect the XBox 360 to TVersity, got to the <strong>Media</strong> blade and select <strong>Videos</strong>. On the device page, select <strong>Computer</strong>. It&#8217;ll give you some direction on how to install <a href="http://www.microsoft.com/windows/windowsmedia/devices/wmconnect/default.aspx">Windows Media Connect</a>, which you can promptly ignore and select <strong>Yes</strong>. The 360 will search for your TVersity Media Server. If it can&#8217;t find it, make sure your computer and 360 are connected to the same network, through a switch/router (don&#8217;t direct connect / crossover), and that your firewall is either disabled or allows incoming network traffic on TCP port 41952.</p>
	<p>Once connected, you should be able to see the list of shared movies added to TVersity. Selecting a movie and playing it should start the movie after a short (&lt; 10 seconds) time. If you get an error saying that the media format is not supported, or a black screen with nothing happening, then you likely have a codec problem and should go back to the first (Uninstall Everything) step and start over. Be sure to try out all your differently encoded content before freaking out to see if it is only one codec that is giving you trouble. For me, I couldn&#8217;t get XviD content to decode because I installed the XviD codecs from K-Lite instead of using ffdshow to decode it.</p>
	<p>You should also note that due to the way your videos are transcoded, you can not fast-forward / rewind videos. TVersity also seems to have a bug where the XBox 360 Media Player will not end immediately after a video is done. Small things to overlook for streaming media to your XBox 360.</p>
	<h4>Other Thoughts &amp; Conclusion</h4>
	<p>If you have Window XP Media Center Edition, and think TVersity is too much of a hassle, I would recommend looking into <a href="http://runtime360.com/projects/transcode-360/">Transcode 360</a> as from what I have heard it is easier to setup, but not as nice to use. Or else you can look into <a href="http://jortega74.free.fr/forum/viewtopic.php?t=33">VLC360</a> (which I have not).</p>
	<p>The unfortunate thing about all of these solutions is that it requires a Windows XP (or Vista) computer in order to work as there currently is no Linux based solution. I have been looking into this however, and based on my time from playing around with <a href="http://www.twonkyvision.de/">TwonkyVision&#8217;s</a> <a href="http://www.twonkyvision.de/Products/TwonkyMedia/index.html">TwonkyMedia</a>, I believe it is possible that with a little bit of CGI scripting you could have it transcode videos on-the-fly using either <a href="http://www.videolan.org/vlc/">VLC</a>, <a href="http://www.mplayerhq.hu/">mencoder</a>, <a href="http://ffmpeg.mplayerhq.hu/">ffmpeg</a>, etc. I don&#8217;t have the time to play with something like this but, if someone is willing to give it a try, let me know how it turns out!
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/stream-transcoded-media-to-your-xbox-360-using-tversity/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>VPNC with Shorewall on OpenWRT</title>
		<link>http://garycourt.com/blog/post/vpnc-with-shorewall-on-openwrt/</link>
		<comments>http://garycourt.com/blog/post/vpnc-with-shorewall-on-openwrt/#comments</comments>
		<pubDate>Sun, 28 May 2006 20:01:50 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Linux</category>
		<guid>http://garycourt.com/blog/post/vpnc-with-shorewall-on-openwrt/</guid>
		<description><![CDATA[	In my previous articles, I discussed how to install and setup OpenWRT on the WRT54GL, and how to setup Shorewall as a firewall solution. Today I will be discussing how to install, setup, and use VPNC to connect to a Cisco VPN 3000 Concentrator, as well as how to configure Shorewall to allow VPN communication [...]]]></description>
			<content:encoded><![CDATA[	<p>In my previous articles, I discussed how to <a href="http://garycourt.com/blog/post/installing-openwrt-on-the-linksys-wrt54gl/">install and setup OpenWRT on the WRT54GL</a>, and how to <a href="http://garycourt.com/blog/post/openwrt-advanced-firewall/">setup Shorewall as a firewall solution</a>. Today I will be discussing how to install, setup, and use <a href="http://www.unix-ag.uni-kl.de/~massar/vpnc/">VPNC</a> to connect to a <a href="http://www.cisco.com/en/US/products/hw/vpndevc/ps2284/index.html">Cisco VPN 3000 Concentrator</a>, as well as how to configure <a href="http://www.shorewall.net/">Shorewall</a> to allow <acronym title="Virtual Private Network">VPN</acronym> communication through the firewall.<br />
<a id="more-17"></a><br />
This article is written assuming a that you are using the same versions of <a href="http://wiki.openwrt.org/">OpenWRT</a> &#038; <a href="http://www.shorewall.net/">Shorewall</a>, and are configured similarly, as discussed in my previous articles.</p>
	<h4>VPNC</h4>
	<p>VPNC has been backported to the White Russian release (although poorly), and can be installed using <code>ipkg</code>. To install, first edit <code>/etc/ipkg.conf</code> and add the following line after the other &#8220;src&#8221; lines:</p>
	<pre>
src backports http://downloads.openwrt.org/backports/rc5
</pre>
	<p>Now to install vpnc:</p>
	<pre>
ipkg update
ipkg install libgcrypt
ipkg install kmod-tun
ipkg install vpnc
</pre>
	<p>The first two installs are required packages that aren&#8217;t (for some reason) installed when you install <code>vpnc</code>. If you try running <code>vpnc</code> right now, you&#8217;ll get the error:</p>
	<pre>
can&#039;t open /dev/net/tun, check that it is either device char 10 200 or (with DevFS) a symlink to ../misc/net/tun (not misc/net/tun): No such file or directory
can&#039;t initialise tunnel interface: No such file or directory
</pre>
	<p><code>vpnc</code> requires the kernel module <code>tun</code>. The vpnc installer adds an entry to <code>/etc/modules.d/</code> to auto-install the module on startup, but it won&#8217;t be started after you install it. To install to so we can use it right now, run:</p>
	<pre>
insmod tun
</pre>
	<p>The configuration settings for <code>vpnc</code> are located in <code>/etc/vpnc/</code>. Open <code>vpnc.conf</code> with an editor (like <code>vi</code>) and add/edit the follow configuration settings: (replace the IP/usernames/passwords with your VPN credentials)</p>
	<pre>
Interface name tun0
IPSec gateway 12.34.56.78
IPSec ID globaluser
IPSec secret globalpass
Xauth username myuser
Xauth password mypass
</pre>
	<p>Now (at the time of this writing), if this package had been setup properly, this would be all we would have to do for <code>vpnc</code>, and we could just run the command <code>vpnc</code> to start the VPN service. However, if you try doing this now, <code>vpnc</code> will fail to find the vpnc.conf file because it is hard-coded to look for <code>/etc/vpnc.conf</code>. We fix this easily by running:</p>
	<pre>
ln -s /etc/vpnc/vpnc.conf /etc/vpnc.conf
</pre>
	<p>Also, when <code>vpnc</code> runs, it trys to write its <acronym title="Process IDentifier">PID</acronym> information to <code>/var/run/vpnc/</code> which doesn&#8217;t exist. We can fix this by running:</p>
	<pre>
mkdir /var/run/vpnc
</pre>
	<p>Were not done yet, and this is the big one. After <code>vpnc</code> connects to the VPN server, it will run <code>/etc/vpnc/vpnc-script</code>. The problem is that this file was originally written for a <acronym title="Bourne-Again SHell">Bash</acronym> environment, but OpenWRT only has <acronym title="bourne SHell">sh</acronym>. If you try running <code>vpnc</code>, you will get the following error:</p>
	<pre>
/etc/vpnc/vpnc-script: 222: Syntax error: Bad for loop variable
</pre>
	<p>Luckily, there&#8217;s only two places in the code that cause conflict with this environment. We will need to edit the <code>vpnc-script</code> and change the <strong>two (2)</strong> instances of this code&#8230;</p>
	<pre>
                for ((i = 0 ; i &lt; CISCO_SPLIT_INC ; i++ )) ; do
                        eval NETWORK=&quot;\${CISCO_SPLIT_INC_${i}_ADDR}&quot;
                        eval NETMASK=&quot;\${CISCO_SPLIT_INC_${i}_MASK}&quot;
                        eval NETMASKLEN=&quot;\${CISCO_SPLIT_INC_${i}_MASKLEN}&quot;
                        set_network_route &quot;$NETWORK&quot; &quot;$NETMASK&quot; &quot;$NETMASKLEN&quot;
                done
</pre>
	<p>&#8230;to&#8230;</p>
	</pre>
	<pre>
                i=0                                                        
                while [ $i -lt $CISCO_SPLIT_INC ] ; do             
                        eval NETWORK=&quot;\${CISCO_SPLIT_INC_${i}_ADDR}&quot;
                        eval NETMASK=&quot;\${CISCO_SPLIT_INC_${i}_MASK}&quot;
                        eval NETMASKLEN=&quot;\${CISCO_SPLIT_INC_${i}_MASKLEN}&quot;
                        set_network_route &quot;$NETWORK&quot; &quot;$NETMASK&quot; &quot;$NETMASKLEN&quot;
                i=`expr $i + 1`
                done
</pre>
	<p>Alrighty, we&#8217;re done. If you run <code>vpnc</code> right now, it should connect and run as a daemon (without throwing any erros). To disconnect, use <code>vpnc-disconnect</code>.<br />
Note that <code>vpnc-script</code> modifies your routing table (<code>route</code>) and your DNS resolutions (<code>/etc/resolv.conf</code>) on connection. You may need to modify this script as necessary.</p>
	<h4>Shorewall</h4>
	<p>Now that we have <code>vpnc</code> configured, lets setup Shorewall.</p>
	<p>First we will create a zone for the VPN in <code>/etc/shorewall/zones</code> &#8230;</p>
	<pre>
vpnc  ipv4
</pre>
	<p>&#8230;, and map the zone to  the interface in <code>/etc/shorewall/interfaces</code>:</p>
	<pre>
vpnc  tun0  detect
</pre>
	<p>The configuration file <code>/etc/shorewall/tunnels</code> is used to specify the VPN tunnels your firewall will be allowing through. The second argument is the zone in which the VPN gateway is behind, and the third argument is the IP of the VPN gateway. Chances are you won&#8217;t need the second line, but I added it there just incase. (You may also need to change <code>udp</code> to <code>tcp</code>, depending on your VPN Concentrator settings)</p>
	<pre>
generic:udp:500    wan  12.34.56.78
generic:tcp:1723  wan  12.34.56.78
</pre>
	<p>Lastly you will need setup any masquerading in <code>/etc/shorewall/masq</code> if you want to access the VPN from local network:</p>
	<pre>
# If the lan and wifi are bridged
tun0    br0
#If you have removed the bridge (seperated them)
tun0    vlan0
tun0    eth1
</pre>
	<p>Were done! Restart Shorewall using <code>shorewall restart</code> and the rules should be applied. We can now run <code>vpnc</code> to setup the VPN connection, and you should be able to connect to the servers behind it. </p>
	<p>If you would like <code>vpnc</code> to be started on startup of Shorewall, add the following:</p>
	<p><code>/etc/shorewall/start</code></p>
	<pre>
vpnc
</pre>
	<p><code>/etc/shorewall/stop</code></p>
	<pre>
vpnc-disconnect
</pre>
	<h4>Conclusion</h4>
	<p>Despite the problem with the VPNC package, its not too difficult to setup a VPN connection with a Cisco VPN Concentrator. If your VPN gateway timeouts after a period of inactivity, you may need to setup a watchdog service that sends small traffic through the tunnel every so often. Your mileage may vary. </p>
	<p>I hope my article was helpful. Please leave comments!
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/vpnc-with-shorewall-on-openwrt/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>JavaScript DOM to BadgerFish Encoder</title>
		<link>http://garycourt.com/blog/post/javascript-dom-to-badgerfish-encoder/</link>
		<comments>http://garycourt.com/blog/post/javascript-dom-to-badgerfish-encoder/#comments</comments>
		<pubDate>Fri, 28 Apr 2006 04:23:40 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Web Development</category>
	<category>JavaScript</category>
		<guid>http://garycourt.com/blog/post/javascript-dom-to-badgerfish-encoder/</guid>
		<description><![CDATA[	The other day, David Sklar decided to come up with an ingenious method translating XML into simple JSON; nicknamed BadgerFish. At about the same time, I was looking for a format in which I could convert XML to JSON without loosing the features of XML yet keeping the JSON objects simple. BadgerFish is about as [...]]]></description>
			<content:encoded><![CDATA[	<p>The other day, <a href="http://www.sklar.com/">David Sklar</a> decided to come up with an ingenious method translating <acronym title="eXtensible Markup Language">XML</acronym> into simple <a href="http://www.json.org/"><acronym title="JavaScript Object Notation">JSON</acronym></a>; nicknamed <a href="http://badgerfish.ning.com/">BadgerFish</a>. At about the same time, I was looking for a format in which I could convert XML to JSON without loosing the features of XML yet keeping the JSON objects simple. BadgerFish is about as close as a good format as I have seen. However, a project I am working on requires an XML <acronym title="Document Object Model">DOM</acronym> in JavaScript to be converted into JSON for easier processing. Being that no one has written one yet, I went ahead and wrote my own - and am offering it free for others to use.<br />
<a id="more-16"></a><br />
There are some differences of my implementation compared to David&#8217;s:</p>
	<ul>
	<li>I don&#8217;t treat the xmlns property any more special then any other property. The original BadgerFish spec states that the xmlns property should be on every node. This is overkill for me, so I left it out.</li>
	<li>I don&#8217;t ignore whitespace text nodes.</li>
	<li>Multiple child text nodes are added to the &#8216;$&#8217; property as an array.</li>
	</ul>
	<p>For limitations of BadgerFish, see the <a href="http://badgerfish.ning.com/">homepage</a>.</p>
	<p>Usage example:</p>
	<pre>
&lt;script language=&quot;text/javascript&quot; src=&quot;BadgerFish.js&quot;&gt;&lt;/script&gt;
&lt;script language=&quot;text/javascript&quot;&gt;
document.write(encode(document).toSource());
&lt;/script&gt;
</pre>
	<p>This is not the best JavaScript I&#8217;ve ever written, as I could have cleaned it up using namespaces and JavaScriptDoc comments, but I wrote it in a hurry. Feel free to tear this apart and use it for your own purposes. </p>
	<p><a href="/wp-content/files/BadgerFish.js">Click here to download</a>.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/javascript-dom-to-badgerfish-encoder/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>OpenWRT Advanced Firewall</title>
		<link>http://garycourt.com/blog/post/openwrt-advanced-firewall/</link>
		<comments>http://garycourt.com/blog/post/openwrt-advanced-firewall/#comments</comments>
		<pubDate>Fri, 24 Feb 2006 06:43:49 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Linux</category>
	<category>Tutorial</category>
		<guid>http://garycourt.com/blog/post/openwrt-advanced-firewall/</guid>
		<description><![CDATA[	In continuation of my previous article on installing OpenWRT on a Linksys WRT54GL, I discuss how to set some of the more advanced network configurations of the router, and how to setup a firewall with traffic shaping.

	Controlling the Network Switch
	If you&#8217;ve had a chance to look at the hardware layout of the WRT54GL, you will [...]]]></description>
			<content:encoded><![CDATA[	<p>In continuation of my previous article on <a href="http://garycourt.com/blog/post/installing-openwrt-on-the-linksys-wrt54gl/">installing OpenWRT on a Linksys WRT54GL</a>, I discuss how to set some of the more advanced network configurations of the router, and how to setup a firewall with traffic shaping.<br />
<a id="more-15"></a></p>
	<h4>Controlling the Network Switch</h4>
	<p><a href="http://garycourt.com/wp-content/images/WRT54_sw2_internal_architecture.png"><img src="http://garycourt.com/wp-content/images/thumb-WRT54_sw2_internal_architecture.png" alt="WRT54GL Internal Architecture" class="alignRight" /></a>If you&#8217;ve had a chance to look at the <a href="http://garycourt.com/wp-content/images/WRT54_sw2_internal_architecture.png">hardware layout of the WRT54GL</a>, you will notice that the router uses <acronym title="Virtual Local Area Network">VLAN</acronym> tagging to seperate the <acronym title="Wide Area Network">WAN</acronym> port from the rest of the switch. This VLAN configuration settings are stored in <acronym title="Non-Volatile Random Access Memory">NVRAM</acronym> and, as such, we can modify them to our heart&#8217;s content. The WRT54G series router&#8217;s switch supports up to 15 VLAN tags which, since there are only 6 switch ports, is overkill. By default, your router will have the following vlan configuration settings: (you can get/set these using <code>nvram</code>)</p>
	<pre>
vlan0ports=&quot;3 2 1 0 5*&quot;
vlan0hwname=et0
vlan1ports=&quot;4 5&quot;
vlan1hwname=et0
</pre>
	<p>For a quick explanation; Each vlan&#8217;s setting are defined in vlan[#][setting]. <em>Ports</em> defines which ports belong to that vlan, and must always include port 5 or the vlan will not be able to talk to the router (making it essentially useless). The asterisk next to the 5 at the end of the ports list indicates that this vlan is the default vlan. <em>Hwname</em> is the physical port the switch is connected to, and should always be <code>et0</code> for the WRT54GL. </p>
	<p>If you would like to add a <acronym title="DeMilitarized Zone">DMZ</acronym> to your router, you can set your nvram settings as such: (this makes port 4 (internal 0) the DMZ)</p>
	<pre>
vlan0ports=&quot;3 2 1 5*&quot;
vlan0hwname=et0
vlan1ports=&quot;4 5&quot;
vlan1hwname=et0
vlan2ports=&quot;0 5&quot;
vlan2hwname=et0
</pre>
	<p>Now that you have the vlan tagging setup properly, you will need to initialize the interface within OpenWRT. First, setup your configuration options for the DMZ zone:</p>
	<pre>
dmz_ifname=vlan2
dmz_proto=static
dmz_ipaddr=192.168.3.1
dmz_netmask=255.255.255.0
</pre>
	<p>Then, make sure in <code>/etc/init.d/S40network</code> that the following line exists:</p>
	<pre>
ifup dmz
</pre>
	<p>At bootup, when the S40network script is run, ifup will look for all nvram settings starting with <code>dmz_</code> and use them to initialize the interface. It is also smart enough to look at <code>[name]_ifname</code> and determine if it is ethernet interface, vlan, or bridge.</p>
	<p>For example, if you look at your lan settings (<code>nvram show | grep &quot;lan_&quot;</code>), it will look something like this:</p>
	<pre>
lan_ifname=br0
lan_ifnames=&quot;vlan0 eth1 eth2 eth3&quot;
lan_proto=static
lan_ipaddr=192.168.1.1
lan_netmask=255.255.255.0
</pre>
	<p>What&#8217;s happening here is that the lan interface is a bridge of <code>vlan0</code> (LAN) and <code>eth1</code> (Wifi). (Don&#8217;t ask about <code>eth2</code> &#038; <code>eth3</code>, I have no idea why they are there) </p>
	<p>If you would like to seperate the LAN from the Wifi network, change your settings to:</p>
	<pre>
lan_ifname=vlan0
lan_ifnames=&quot;vlan0 eth2 eth3&quot;
lan_proto=static
lan_ipaddr=192.168.1.1
lan_netmask=255.255.255.0
&nbsp;
wifi_ifname=eth1
wifi_proto=static
wifi_ipaddr=192.168.2.1
wifi_netmask=255.255.255.0
</pre>
	<p>Then make sure <code>/etc/init.d/S40network</code> has the following line within it:</p>
	<pre>
ifup wifi
</pre>
	<p>Just reboot and your seperated.</p>
	<p>Note that if you are adding more zones to your router, you should also configure your other services such as firewall script and DHCP client to take advantage of the new configuration.</p>
	<p>For dnsmasq, you should add something like the following to <code>/etc/dnsmasq.conf</code>:</p>
	<pre>
dhcp-range=lan,192.168.1.100,192.168.1.199,255.255.255.0,24h
dhcp-range=wifi,192.168.2.100,192.168.2.199,255.255.255.0,1h
dhcp-range=dmz,192.168.3.100,192.168.3.199,255.255.255.0,24h
</pre>
	<p>You should also allow the &#8220;safe&#8221; zones to talk among each other by adding the following firewall rules to <code>/etc/init.d/S45firewall</code>:</p>
	<pre>
&#46;..
WIFI=$(nvram get wifi_ifname)  #add if LAN/Wifi are seperated
DMZ=$(nvram get dmz_ifname)  #add if you have a DMZ zone
&#46;..
#replace references to br0
iptables -A FORWARD -i $LAN -o $LAN -j ACCEPT
iptables -A FORWARD -i $LAN -o $WAN-j ACCEPT
&nbsp;
#add if wifi is seperated
iptables -A FORWARD -i $LAN -o $WIFI-j ACCEPT
iptables -A FORWARD -i $WIFI-o $LAN -j ACCEPT
iptables -A FORWARD -i $WIFI-o $WAN-j ACCEPT
iptables -A FORWARD -i $WIFI-o $WIFI-j ACCEPT
&nbsp;
#add if dmz is available
iptables -A FORWARD -i $LAN -o $DMZ -j ACCEPT
iptables -A FORWARD -i $WIFI -o $DMZ -j ACCEPT  #if wifi is also seperated
&#46;..
</pre>
	<h4>Firewall Made Easy</h4>
	<p>Despite your experience with iptables, this network routing program is hard to read and even harder to remember all the switches when its time to add a new rule to your firewall. Thankfully there is a much easier way to configure your firewall, and it&#8217;s called <a href="http://www.shorewall.net/">Shorewall</a>. </p>
	<blockquote><p>The Shoreline Firewall, more commonly known as &#8220;Shorewall&#8221;, is a high-level tool for configuring Netfilter. You describe your firewall/gateway requirements using entries in a set of configuration files. Shorewall reads those configuration files and with the help of the iptables utility, Shorewall configures Netfilter to match your requirements.</p></blockquote>
	<p>You can download one of the latest builds of Shorewall for the OpenWRT from <a href="http://openwrt.homelinux.net/">Fabio Longarai&#8217;s OpenWRT site</a>. To install Shorewall, it&#8217;s as simple as:</p>
	<pre>
cd /tmp
wget http://openwrt.homelinux.net/shorewall_x.x.x_mipsel.ipk
ipkg install shorewall_x.x.x_mipsel.ipk
rm shorewall_x.x.x_mipsel.ipk
</pre>
	<p><strong>Note that the following guide was written for Shorewall v3.0.4-2.</strong></p>
	<p>All your configuration files can be found in <code>/etc/shorewall/</code>. Since every person&#8217;s needs and router settings are unique, their firewall will be unique as well. As such, the following configuration settings are stereotypical settings only and should be customized to one&#8217;s needs. For more information on configuring Shorewall, please see the <a href="http://www.shorewall.net/Documentation_Index.html">official documentation</a>.</p>
	<p>For beginners to Shorewall, I recommend tackling the firewall files in the following order:</p>
	<h5><code>zones</code></h5>
	<p>This file specifies the available zones you want to control by your firewall. The names of zones are nothing more then aliases, and as such Shorewall has no understanding of the meaning of them. Do not assume a zone called DMZ will behave like a DMZ zone.</p>
	<pre>
###############################################################################
#ZONE   TYPE            OPTIONS         IN                      OUT
#                                       OPTIONS                 OPTIONS
fw      firewall
lan     ipv4
wifi    ipv4
dmz     ipv4
wan     ipv4
#LAST LINE
</pre>
	<h5><code>policy</code></h5>
	<p>This file defines the default behavior for a zone. Any zone is allowed to talk to itself, so you don&#8217;t need to specify a zone in both the source and destination. Also, (assuming your networking is A->FW->B) just because A can talk to FW, doesn&#8217;t mean that A can talk to B - you must explicitely define it. </p>
	<p>You can also, in this file, define what the default behavior of traffic being forwarded from one zone to another is and the type of logging the firewall does.</p>
	<pre>
###############################################################################
#SOURCE         DEST            POLICY          LOG             LIMIT:BURST
#                                               LEVEL
fw      all     ACCEPT
lan     all     ACCEPT
wifi    all     ACCEPT
dmz     fw      ACCEPT
dmz     wan     ACCEPT
dmz     all     REJECT  notice
wan     dmz     ACCEPT
wan     all     DROP
all     all     REJECT  notice
#LAST LINE
</pre>
	<h5><code>interfaces</code></h5>
	<p>In this file, you define the interfaces and how they map to the available zones. You can also specify options on restricting what types of erronious traffic can be let through.</p>
	<pre>
###############################################################################
#ZONE   INTERFACE       BROADCAST       OPTIONS
lan     vlan0   detect  routeback,dhcp
wifi    eth1    detect  routeback,tcpflags,dhcp,routefilter,detectnets,nosmurfs
dmz     vlan2   detect  routeback,dhcp
wan     vlan1   detect  routeback,tcpflags,blacklist,dhcp,routefilter,nosmurfs
#LAST LINE
</pre>
	<h5><code>masq</code></h5>
	<p>This file defines how source <acronym title="Network Address Translation">NAT</acronym>-ing is done through the firewall, and through which interface.</p>
	<pre>
###############################################################################
#INTERFACE              SUBNET          ADDRESS         PROTO   PORT(S) IPSEC
vlan1     vlan0
vlan1     eth1
vlan1     vlan2
#LAST LINE
</pre>
	<h5><code>rules</code></h5>
	<p>This is the brain of your firewall, where you define the complicated exceptions to the default policy and let traffic through. A lot can be done in this file, so be sure to <a href="http://www.shorewall.net/Documentation.htm#Rules">read up on it</a>. For this example, I&#8217;m going to allow pings to the firewall, and incoming BitTorrent to my main system. The first rules uses a macro while the second is a typical rule that employs <acronym title="Destination Network Address Translation">DNAT</acronym>-ing.</p>
	<pre>
#############################################################################################################
#ACTION SOURCE          DEST            PROTO   DEST    SOURCE          ORIGINALRATE            USER/
#                                               PORT    PORT(S)         DEST   LIMIT            GROUP
#SECTION ESTABLISHED
#SECTION RELATED
SECTION NEW
Ping/ACCEPT     wan     fw
DNAT            net     lan:192.168.1.100 tcp     6881:6889   -
#LAST LINE &#45;- ADD YOUR ENTRIES BEFORE THIS ONE &#45;- DO NOT REMOVE
</pre>
	<h5><code>routestopped</code></h5>
	<p>The rules in this file define the default behavior when Shorewall is stopped. For the most part, to allow &#8220;safe&#8221; zones to talk properly when Shorewall is stopped, added them to this file as so:</p>
	<pre>
###############################################################################
#INTERFACE      HOST(S)                 OPTIONS
vlan0   -       source
eth1    -       source
vlan2   -       source
#LAST LINE    
</pre>
	<h5><code>tos</code></h5>
	<p>Unfortunately, OpenWRT&#8217;s iptables does not support <acronym title="Type Of Service">TOS</acronym>, so don&#8217;t bother adding any entries to this file.</p>
	<h5><code>params</code></h5>
	<p>For the most part, if you are doing basic firewalling, you can ignore the rest of the files in this folder. The only other file you may be interested in is <code>params</code>, where you can define variables to be used in the other config files in this directory. For example, you could put in this file&#8230;</p>
	<pre>
$LAN_ZONE=lan
$LAN_IFNAME=$(nvram get lan_ifname)
$LAN_BROADCAST=192.168.1.255
&#46;..
</pre>
	<p>&#8230; and then, you could use these variables in your scripts &#8230;</p>
	<pre>
/etc/shorewall/interfaces:
&#46;..
$LAN_ZONE    $LAN_IFNAME    $LAN_BROADCAST    $LAN_OPTIONS
&#46;..
</pre>
	<p>&#8230; in order to simplify the changing of your network configurations.</p>
	<h4>Traffic Control</h4>
	<p>One of my primary goals of setting up a dedicated firewall was to have Traffic Shaping/<acronym title="Quality Of Service">QoS</acronym> determine the priority of my internet traffic and adjust accordingly based on the needs to the network. For example, my primary network traffic is <acronym title="Voice Over IP">VoIP</acronym>, BitTorrent, and HTTP/web. I want VoIP to have the highest priority of my network communications, while BitTorrent to be the lowest. Therefore, my phone conversations won&#8217;t drop when I&#8217;m downloading heavy.</p>
	<p>In order to use traffic shaping, you must have the <code>tc</code> package installed. You can do this by running:</p>
	<pre>
ipkg install tc
</pre>
	<p>It should be noted before you start that you can only shape outbound traffic. You may ask why, but think about how a network works. The router can only make a decision on what packet has priority over another packet when it has received that packet and examined it. Therefore, it does not make sense to shape incoming traffic since <em>a)</em>your internal network is likely must faster then your incoming internet traffic thus making prioritization useless, and <em>b)</em> you&#8217;ve already received the packet, so you might as well just send it on its way (your ISP has determined which packet was important to go down the line first).</p>
	<h5><code>tcdevices</code></h5>
	<p>First, you need to define the devices on your router you would like to enable traffic shaping on. You can do this by editing the <code>tcdevices</code> config file:</p>
	<pre>
###############################################################################
#INTERFACE      IN-BANDWITH     OUT-BANDWIDTH
wan     5mbit   512kbit
#LAST LINE &#45;- ADD YOUR ENTRIES BEFORE THIS ONE &#45;- DO NOT REMOVE
</pre>
	<p>You should set these settings to your theoretical maximum speed on that line. If traffic starts moving faster then these defined settings, the router will begin dropping packets in order to slow down the traffic.</p>
	<h5><code>tcclasses</code></h5>
	<p>For my purposes, I created five &#8220;buckets&#8221; to prioritize my traffic in. Note that a higher priority will get served first (till its empty) before a lower priority is served. In the example below, priority 4 is the default priority and all unmarked traffic will go  into this priority queue. I also auto-marked all (small) ACK packets as highest priority to artifically speed up downloads.</p>
	<pre>
###############################################################################
#INTERFACE      MARK    RATE    CEIL    PRIORITY        OPTIONS
br1     1       full    full    1       tcp-ack #CRITICAL
br1     2       full    full    2               #HIGH
br1     3       full    full    3               #NORMAL
br1     4       full    full    4       default #LOW
br1     5       full    full    5               #USELESS
#LAST LINE &#45;- ADD YOUR ENTRIES BEFORE THIS ONE &#45;- DO NOT REMOVE
</pre>
	<h5><code>tcrules</code></h5>
	<p>Finally, this is the file where we specify how our traffic is prioritized. I wanted my VoIP traffic to be priority 2, my common internet traffic as priority 3, and my BitTorrent traffic and everything else as 4. The reason I did not make priority 3 my default and then just (add rules to) put BitTorrent in priority 4 is due to the fact that my BitTorrent client does not allow me to define the source ports of outbound traffic. So instead, any unrecognized traffic gets low priority.</p>
	<p>In the example below, I specify that Pings &#038; Rdate (time update) requests are highest priority, VoIP traffic &#038; DNS requests are next highest, my common internet traffic (HTTP, SSH, FTP) are next, and everything else is last.</p>
	<pre>
###############################################################################
#MARK   SOURCE          DEST            PROTO   PORT(S) CLIENT  USER    TEST
#                                                       PORT(S)
1       vlan0,eth1      0.0.0.0/0       icmp    8               #Ping
1       vlan0,eth1      0.0.0.0/0       tcp     37              #Rdate
2       vlan0           0.0.0.0/0       udp     5060:5061       #VoIP
2       vlan0           0.0.0.0/0       udp     16384:16482     #VoIP
2       vlan0,eth1      0.0.0.0/0       udp     53              #DNS
2       vlan0,eth1      0.0.0.0/0       tcp     53              #DNS
3       vlan0,eth1      0.0.0.0/0       tcp     80              #HTTP
3       vlan0,eth1      0.0.0.0/0       tcp     22              #SSH
3       vlan0,eth1      0.0.0.0/0       tcp     20              #FTP-DATA
3       vlan0,eth1      0.0.0.0/0       tcp     21              #FTP
#LAST LINE &#45;- ADD YOUR ENTRIES BEFORE THIS ONE &#45;- DO NOT REMOVE
</pre>
	<p>For more advanced rules, <a href="http://www.shorewall.net/traffic_shaping.htm#tcrules">see the docs</a>.</p>
	<h4>Conclusion</h4>
	<p>Last thing, in order to start using Shorewall, use the command <code>shorewall start</code>. If you would like to have Shorewall start on bootup, add the following code to <code>/etc/init.d/S46shorewall</code>. (Don&#8217;t forget to make it executable: chmod a+x S46shorewall)</p>
	<pre>
#!/bin/bash
shorewall start
</pre>
	<p><strong>Please note</strong> that you can easily prevent yourself from accessing the <acronym title="Command Line Interface">CLI</acronym> with Shorewall. And if Shorewall starts on startup, a reset will not fix the problem. Please thoroughly test your firewall scripts before auto-starting shorewall on startup.</p>
	<p>Well, its getting late and I need to crash. I hope you enjoyed the article, and look forward to reading your comments. If you would like more information on a particular section, feel free to drop me a note and I&#8217;ll look into updating it. Later!
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/openwrt-advanced-firewall/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Installing OpenWRT on the Linksys WRT54GL</title>
		<link>http://garycourt.com/blog/post/installing-openwrt-on-the-linksys-wrt54gl/</link>
		<comments>http://garycourt.com/blog/post/installing-openwrt-on-the-linksys-wrt54gl/#comments</comments>
		<pubDate>Fri, 10 Feb 2006 04:36:02 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Linux</category>
	<category>Tutorial</category>
		<guid>http://garycourt.com/blog/post/installing-openwrt-on-the-linksys-wrt54gl/</guid>
		<description><![CDATA[	Linksys really hit a niche when they created the WRT54G line of wireless routers, although unintentional. These particular routers were originally written using Linux which, due to the GPL, requires Linksys to release the source code. Since then, many open source groups have gotten ahold of this code and hacked it to bits. As such, [...]]]></description>
			<content:encoded><![CDATA[	<p><img src='/wp-content/images/wrt54gl.jpg' alt='Linksys WRT54GL' class="alignRight" /><a href="http://www.linksys.com/">Linksys</a> really hit a niche when they created the <a href="http://en.wikipedia.org/wiki/WRT54G">WRT54G</a> line of wireless routers, although unintentional. These particular routers were originally written using Linux which, due to the <a href="http://www.gnu.org/copyleft/gpl.html"><acronym title="General Public License">GPL</acronym></a>, requires Linksys to release the source code. Since then, many open source groups have gotten ahold of this code and hacked it to bits. As such, there are many different open source firmwares available for the WRT54G line of routers that you can install. (Warranty voiding of course) </p>
	<p>One of the most popular third-party firmware available is <a href="http://openwrt.org/">OpenWRT</a>. This firmware is essentially a stripped-down embedded Linux operation system with addon packages to allow it to be a wireless router. It&#8217;s small, simple, and powerful; though not for the light of geek, as any configuration must be done by <acronym title="Command Line Interface">CLI</acronym>.</p>
	<p>I recently got a WRT54GL wireless router, which is the same as a WRT54G v4 router. (Linksys changed the model number since v5 does not use Linux and will not run custom firmwares.) In only a few hours, I was able to install OpenWRT and setup a powerful router/firewall for my home network. Here&#8217;s how you can too&#8230;<br />
<a id="more-14"></a></p>
	<h4>Installing OpenWRT</h4>
	<p>There are two ways to install OpenWRT: the easy way, or the safe way. Now, one should follow the safe way as it is, hence, safe. However, it is also the most difficult way. Essentially what you want to do is reflash the router using <acronym title="Trivial File Transfer Protocol">TFTP</acronym>; that is, if something goes wrong during the flash, you can just try again. In order to do this method, you need to enable <code>boot_wait</code> on the router. There used to be a very easy way of doing this on the older WRT54G routers using the <a href="http://wiki.openwrt.org/OpenWrtDocs/Installing#head-76921c79e7c7ed3b03d3bc9a40b1a2c792c215b0">Ping hack</a>. However, Linksys has such patched this vulnerability and the only way to enable this feature is to downgrade the router to a previous version (&lt; 3.01.3).</p>
	<p>Now, the easy way is to just use Linksys&#8217; Firmware Upgrade page and upload OpenWRT to the router. The only problem with this method that is if anything goes wrong you&#8217;ve got a bricked router. However, as long as you don&#8217;t bump any cords, use a bad firmware, or loose power during the flash and powerup, things will be fine. Since no challenge is without its risks, I decided to go about this route.</p>
	<p>You can download the latest version of OpenWRT from the official website at <a href="http://downloads.openwrt.org/">http://downloads.openwrt.org/</a>. </p>
	<p><strong>Note that this document is written for the WhiteRussian release.</strong></p>
	<p>The are several different versions of the firmware available depending on the hardware and filesystem configuration you want. The WRT54GL is the same as a WRT54G, so download the WRT54G firmware. There is also two different filesystem configurations you can have. </p>
	<p>SquashFS is the recommended, more secure setup as it has a two part filesystem. One area is read-only which contains all the files that came with the firmware, while the other area is read/write which is the root of the file system and contains symlinks to the read-only files. OpenWRT recommends this setup since it reduces the chance of one rewritting something they shouldn&#8217;t. However, it also doesn&#8217;t restrict the normal usage as you can remove the symlinks and replace the file with one of your own (the extra step offers accidental protection). This is the setup I went with.</p>
	<p>For completion sake, the JFFS2 setup is just a normal read/write filesystem that doesn&#8217;t offer a proper failsafe mode.</p>
	<p>By using the Linksys Firmware Upgrade page on the router&#8217;s web administration pages, select the firmware to be uploaded and click on &#8220;Update&#8221;. It takes awhile to reflash the router so don&#8217;t hold your breath. At first, the textbox on the bottom will show somewhat of a progress bar. When the bars reach the end of the text field, the page will change indicating the router has been updated. DO NOT DO ANYTHING! Look at your router. If the DMZ light is on, it means that OpenWRT is booting up. It will take some time to start and initialize so you must be patient some more. You are not free to do anything until the DMZ light turns off and the router is operational. Then, and only then, can you proceed to the next step.</p>
	<p>First thing you should do is log into the router via telent. (Remember, OpenWRT is primarily a CLI OS, so get comfortable with it) You should be able to access it by the previously set IP address, and no password is required (yet).</p>
	<pre>
root@localhost:~$ telnet 192.168.1.1
Trying 192.168.1.1&#46;..
Connected to 192.168.1.1.
Escape character is &#039;^]&#039;.
&nbsp;
BusyBox v1.00 (2005.09.22-14:58+0000) Built-in shell (ash)
Enter &#039;help&#039; for a list of built-in commands.
&nbsp;
  _______                     ________        __
 |       |.&#45;&#45;&#45;&#8211;.&#45;&#45;&#45;&#8211;.&#45;&#45;&#45;&#8211;.|  |  |  |.&#45;&#45;&#45;-.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 WHITE RUSSIAN  &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-
  * 2 oz Vodka   Mix the Vodka and Kahlua together
  * 1 oz Kahlua  over ice, then float the cream or
  * 1/2oz cream  milk on the top.
 &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-
root@OpenWrt:~#
</pre>
	<p>The first thing (after having logged in) that you should do right away is to turn <code>boot_wait</code> on. This is important since if you ever screw up in the future (as in, can&#8217;t log in), you can always reflash the firmware using the <a href="http://wiki.openwrt.org/OpenWrtDocs/Installing#head-344b77cce4d63bd941eb782ea25d37f9e8fd9d19">TFTP method</a>. Otherwise, you may end up with a bricked router.</p>
	<p>To do this, run at the command line:</p>
	<pre>
nvram set boot_wait=on
nvram commit
</pre>
	<p>For more information on <code>nvram</code>, <a href="http://wiki.openwrt.org/OpenWrtDocs/Configuration#head-cd2767b4bfa519c2708465c673feafcff96fd3c5">see the wiki</a>.</p>
	<h4>Securing your new box</h4>
	<p>It is recommended that you set a password for your root account so random people can&#8217;t just take over your box (this should be obvious). You can do this with the <code>passwd</code> command. </p>
	<p>After setting a new password, the OS will automatically install and enable the SSH server (<a href="http://matt.ucc.asn.au/dropbear/dropbear.html">dropbear</a>). It will also disable telnet logins but, unfortunately, will keep the daemon running. You can free up some resources by doing the following:</p>
	<pre>
killall telnetd
rm /etc/init.d/S50telnet
</pre>
	<p>Next is to secure your wireless access points. If you already secured your <acronym title="Wireless Access Point">WAP</acronym> while it was running the Linksys firmware, then this step is done - unless your using WPA/WPA2 encryption, in which you have one step left (see below). If not, then you will have several settings you need to change. Since my access point was already locked down I didn&#8217;t have to do this step. However, I will do my best to guide you in case you didn&#8217;t.</p>
	<p><code>nvram</code> refers to the wireless adapter as <code>wl0</code>, so we can see all the available configuration options for this interface by doing the following:</p>
	<pre>
nvram show | grep &quot;wl0&quot;
</pre>
	<p>I won&#8217;t print the list here as there are quite a few options to change. To save you some time, if you need to get your access point working, make sure the following options are set:</p>
	<pre>
#WPA mode
#ap = Access Point (master mode), sta = Client mode
wl0_mode=ap
&nbsp;
#WPA SSID
wl0_ssid=wap
&nbsp;
#WPA channel
#For North America: 1..11
wl0_channel=6 #channel access point is on
&nbsp;
#WPA intrastructure
#0 = Ad Hoc mode, 1 = normal AP/Client mode
wl0_infra=1
&nbsp;
#WPA broadcast SSID
#0 = on, 1 = off
wl0_closed=0
</pre>
	<p>Note that you must commit any changes that are made to nvram before they can take effect. If you find your changes (after committing) don&#8217;t have any effect, you may need to reboot the router. </p>
	<pre>
nvram set option=value    #example
nvram set option2=value2  #don&#039;t acually do
&#46;..
nvram commit
</pre>
	<p>Anyways, back to security. If you would like to enable mac filtering:</p>
	<pre>
#WPA MAC filter
#disabled = any MAC allowed, allow = only listed MACs allowed, deny = deny only listed MACs
wl0_macmode=allow
&nbsp;
#WPA MAC filter list
#Space seperated list of MAC address to allow/deny
wl0_maclist=&quot;00:02:2D:08:E2:1D 00:03:3E:05:E1:1B&quot;
</pre>
	<p>The WRT54GL supports both <a href="http://en.wikipedia.org/wiki/WEP"><acronym title="Wired Equivalent Privacy">WEP</acronym></a> and <a href="http://en.wikipedia.org/wiki/Wi-Fi_Protected_Access"><acronym title="Wi-Fi Protected Access">WPA</acronym></a> encryption. WPA is much stronger then WEP, and is highly recommended unless you need to provide legacy access to outdated equipment. If your going to use WEP, you should take other precautions such as MAC filtering.  To enable WEP:</p>
	<pre>
#WPA WEP encryption
#disabled = disable WEP, enabled = enable WEP
wl0_wep=enabled
&nbsp;
#WPA WEP key number
#Selects which key (wl0_key[1-4]) to use for WEP encryption: 1..4
wl0_key=1
&nbsp;
#WPA WEP key [1..4]
#WEP key in hexadecimal format (allowed hex chars are 0-9a-f)
#Don&#039;t use WEP keys with 00 at the end. 128 bit WEP key must be 26 hex digits long.
wl0_key1=supersecretkey1
wl0_key2=supersecretkey2
wl0_key3=supersecretkey3
wl0_key4=supersecretkey4
</pre>
	<p>For the rest of us, here are the options needed to configure WPA:<br />
<em>Note that enabling WPA disables WEP.</em></p>
	<pre>
#WAP WPA mode
# open = No WPA
# psk = WPA Personal/PSK (Preshared Key)
# wpa = WPA with a RADIUS server
# psk2 = WPA2 Personal/PSK
# wpa2 = WPA2 with RADIUS
# &quot;psk psk2&quot; = Both WPA and WPA2 Personal/PSK
# &quot;wpa wpa2&quot; = Both WPA and WPA2 with RADIUS
wl0_akm=&quot;psk psk2&quot;
&nbsp;
#WPA WAP encryption algorithm
#tkip = RC4 encryption, aes = AES encryption, &quot;aes+tkip&quot; = support both 
wl0_crypto=&quot;aes+tkip&quot;
&nbsp;
#WPA WAP preshared key
#Password to use with WPA/WPA2 PSK (at least 8, up to 63 chars)
wl0_wpa_psk=supersecretkey
&nbsp;
#RADIUS server information
wl0_radius_key=
wl0_radius_ipaddr=
wl0_radius_port=
</pre>
	<p>Note that WPA does not work with the default install, and requires you to install the NAS package before you can authenticate. You can easily do so by running:</p>
	<pre>
ipkg install nas
</pre>
	<h4>Setting up neccessary services</h4>
	<h5>Cron</h5>
	<p>There are a bunch of services you should likely setup before putting your router in production. One of those services is <a href="http://en.wikipedia.org/wiki/Cron">cron</a>. There are two steps to setting up cron. First is to create the <code>crontabs</code> file in <code>/etc/</code>:</p>
	<pre>
mkdir /etc/crontabs
touch /etc/crontabs/root
ln -sf /etc/crontabs/root /etc/crontab
</pre>
	<p>The last two lines are for compatibility/habit sake as many Linux distributions typically keep cron information in <code>/etc/crontab</code>.</p>
	<p>The other step is to have cron startup automatically on boot. You can do so by creating the file <code>/etc/init.d/S60cron</code> with:</p>
	<pre>
#!/bin/sh
[ -d /etc/crontabs ] &amp;&amp; crond -c /etc/crontabs
</pre>
	<p>You can then start cron by running this script:</p>
	<pre>
chmod 775 S60cron  #Make script executable, only need to do once
./S60cron
</pre>
	<h5>Date/Time</h5>
	<p>If you haven&#8217;t noticed yet, your router will not have its time set. One of the problems with the WRT54G line is that they do not have an internal clock, so they loose their time after resets. Furthermore, they are horrible for drifting. So, we will need to set their internal date/time on boot, and periodically (good thing we have cron).</p>
	<p>Before we start though, we should set our timezone. You can do this by writing a timezone identifier to <code>/etc/TZ</code>. For example, for me, I did:</p>
	<pre>
echo &quot;MST7MDT&quot; &gt; /etc/TZ
</pre>
	<p>You can find out more information on the TZ file <a href="http://wiki.openwrt.org/OpenWrtDocs/Configuration#head-29ce2ea9da8dfba2f1c0dc0eca6fec0a138df148">here</a>.</p>
	<p>Now, to set time on bootup, add the file <code>/etc/init.d/S42rdate</code> with the following:</p>
	<pre>
#!/bin/sh
/usr/sbin/rdate 192.43.244.18  #time.nist.gov
</pre>
	<p>To keep your clock up-to-date, add the following line to <code>/etc/crontab</code>:</p>
	<pre>
0 * * * * /etc/init.d/S42rdate  #syncs every hour
</pre>
	<h5>Dnsmasq</h5>
	<p>One of the things you should check on before getting too comfortable with your setup is to look at <a href="http://thekelleys.org.uk/dnsmasq/doc.html">Dnsmasq</a>, <em>&#8220;a lightweight, easy to configure DNS forwarder and DHCP server.&#8221;</em> There was not much I had to change here, but you should be familiar with it incase you want to have control of your DHCP assignments. For example, you can see in this file that you can control static DHCP assignments by adding entries into <code>/etc/ethers</code>. You can find more information on dnsmasq <a href="http://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html">here</a>, and an example configuration script <a href="http://thekelleys.org.uk/dnsmasq/docs/dnsmasq.conf.example">here</a>.</p>
	<p>This will likely be the first file that you have run into that is read-only as it is a symbolic link to the file in the rom. If you want to edit this file (or any other default file), simply run something like:</p>
	<pre>
rm dnsmasq.conf
cp /rom/etc/dnsmasq.conf /etc/dnsmasq.conf
</pre>
	<h4>Firewall</h4>
	<p>I could spend all day telling you about how to setup OpenWRT to be the be-all, end-all of all routers. However, I have completed the goal of this article by describing how to install OpenWRT, and how to configure some basic essentials.</p>
	<p>One of the things you should look at before forgetting your router password is setting up the firewall rules. I&#8217;m not going to go into details on this, but OpenWRT uses <a href="http://www.netfilter.org/projects/iptables/"><code>iptables</code></a> for its firewall rules. You could either configure it using <code>iptables</code> by editing <code>/etc/firewall.user</code>, or install something like <a href="http://www.shorewall.net/">Shorewall</a> and use its easier to define scripting language.</p>
	<p><ins datetime="2006-02-24T06:47:11+00:00"><strong>Update:</strong> <a href="http://garycourt.com/blog/post/openwrt-advanced-firewall/">I have written an article</a> on how to setup a firewall using Shorewall on the WRT54GL, including other advanced topics such as customizing the internal switch and traffic shaping.</ins></p>
	<p><a href="/wp-content/images/WRT54_sw2_internal_architecture.png"><img src='/wp-content/images/thumb-WRT54_sw2_internal_architecture.png' alt='WRT54GL Internal Architecture' class="alignRight" /></a>You should also be familiar with how the WRT54GL&#8217;s hardware maps to the network interfaces. You can see from <a href="/wp-content/images/WRT54_sw2_internal_architecture.png">this picture</a> how things are wired, and is a good blueprint to keep around.</p>
	<h4>Conclusion</h4>
	<p>Well, hopefully this article helps and your roqing with your new connection hub. If you liked this article (or found some errors), please report them in the comments below.  &#8216;night!
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/installing-openwrt-on-the-linksys-wrt54gl/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Changing Permalink Structure in WordPress</title>
		<link>http://garycourt.com/blog/post/changing-permalink-structure-in-wordpress/</link>
		<comments>http://garycourt.com/blog/post/changing-permalink-structure-in-wordpress/#comments</comments>
		<pubDate>Thu, 02 Feb 2006 03:35:02 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Personal</category>
	<category>Web Development</category>
	<category>Tutorial</category>
	<category>WordPress</category>
		<guid>http://garycourt.com/blog/post/changing-permalink-structure-in-wordpress/</guid>
		<description><![CDATA[	Permalinks are a necessity in today&#8217;s online world. With the speed at which information is moving, it needs a way of always being referenced to without it &#8220;disappearing&#8221;. Permalinks are nothing more then a URL that will always point to the target information, regardless if it moves or not. WordPress has a built in permalink [...]]]></description>
			<content:encoded><![CDATA[	<p><a href="http://en.wikipedia.org/wiki/Permalink">Permalinks</a> are a necessity in today&#8217;s online world. With the speed at which information is moving, it needs a way of always being referenced to without it &#8220;disappearing&#8221;. Permalinks are nothing more then a URL that will always point to the target information, regardless if it moves or not. <a href="http://wordpress.org/">WordPress</a> has a built in permalink feature for posts and pages which works as intended. Unfortunately, permalinks are permanent, and if you don&#8217;t plan ahead, you could be stuck with a permalink structure that you do not like. I initially thought that the permalink structure I had setup on my website was well thought of and practical. However, in practice, I changed my mind and wanted a different permalink structure. I also didn&#8217;t want to break any links people had already made to my site. Here&#8217;s how I went about it&#8230;<br />
<a id="more-13"></a></p>
	<h4>Changing Permalink Structure</h4>
	<p>My initial permalink structure for posts was structured as such:<br />
<code>http://garycourt.com/blog/post/13</code></p>
	<p>The problem with this structure is that just by looking at the URL, you are unable to determine what the content is about. A more common approach to permalinks (by other blogs) is to have the title in the URL, which I decided on, like so:<br />
<code>http://garycourt.com/blog/post/changing-permalink-structure-in-wordpress/</code></p>
	<p>Now, luckily for me, it is fairly simple for me to make this change while maintain backwards compatibility with the old permalink structure. How? Well, the only difference is that the old URL always ended in a number, while the new URL always ends in characters. We can write rules that will be able to easily determine the difference.</p>
	<p>WordPress keeps it&#8217;s URL structure rules in <code>.htaccess</code>, in the root of the WordPress directory. The rewrite rules are written using <a href="http://httpd.apache.org/">Apache&#8217;s</a> <a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html">mod_rewrite</a>.</p>
	<p>First, to maintain backwards compatibility with the old permalink structure, I copied the old URL rewrite code that finds blog posts. I then pasted this code, with some modification, above WordPress&#8217;s URL rewrite code.</p>
	<pre>
# Begin Old Permalinks
&lt;ifmodule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [S=6]
RewriteRule ^blog/post/([0-9]{4})/?.*$ - [S=5]  #Prevent breaking of year view
RewriteRule ^blog/post/([0-9]+)/trackback/?$ /index.php?p=$1&amp;tb=1 [QSA,L]
RewriteRule ^blog/post/([0-9]+)/feed/(feed|rdf|rss|rss2|atom)/?$ /index.php?p=$1&amp;feed=$2 [QSA,L]
RewriteRule ^blog/post/([0-9]+)/(feed|rdf|rss|rss2|atom)/?$ /index.php?p=$1&amp;feed=$2 [QSA,L]
RewriteRule ^blog/post/([0-9]+)/page/?([0-9]{1,})/?$ /index.php?p=$1&amp;paged=$2 [QSA,L]
RewriteRule ^blog/post/([0-9]+)(/[0-9]+)?/?$ /index.php?p=$1&amp;page=$2 [QSA,L]
&lt;/ifmodule&gt;
# End Old Permalinks
</pre>
	<p>If your wondering what I changed, I added the first 6 lines (which I copied from the beginning of the WordPress&#8217;s rules, and added the seventh line to prevent breaking of year view (since this rule must always come before post view rules).</p>
	<p>I then went into WordPress and changed the permalink structure from:</p>
	<pre>/blog/post/%postid%</pre>
	<p>to:</p>
	<pre>/blog/post/%postname%/</pre>
	<p>Now, by going to either permalink structure, they will get the same post.</p>
	<h4>Forcing New Permalink Structure</h4>
	<p>Ideally, we want all users using the old permalink structure to update their links to the new structure. The HTTP protocol has a response code for that purpose: <em>301 Moved Permanently</em>. This redirect response will send back a new URL which the content being requested can now permanently be found at.</p>
	<p>I found a really nice WordPress plugin that does this extremely easily: <a href="http://fucoder.com/code/permalink-redirect/">Permalink Redirect</a>. Essentially this plugin will check the requested URL against a post&#8217;s permalink, and if they don&#8217;t match, sends a <em>301 Moved Permanently</em> response for the new permalink URL. All you have to do is install the plugin, and your done!</p>
	<h4>Conclusion</h4>
	<p>There are many ways of changing your permalink structure without breaking pre-existing links, and this is just one way. Note, however, that all target permalink structures may not be possible. I got lucky and was able to change my structure effortlessly.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/changing-permalink-structure-in-wordpress/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>PHP OSGi Framework Concept</title>
		<link>http://garycourt.com/blog/post/php-osgi-framework-concept/</link>
		<comments>http://garycourt.com/blog/post/php-osgi-framework-concept/#comments</comments>
		<pubDate>Mon, 23 Jan 2006 23:10:24 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>PHP</category>
		<guid>http://garycourt.com/blog/post/php-osgi-framework-concept/</guid>
		<description><![CDATA[	One of the things I&#8217;ve always wanted to write, ever since I started writing web backends, is a proper extendable (plugin) framework in PHP. I&#8217;ve spent a little time searching for something that would fit my needs, but surprisingly there are very few free, documented plugin frameworks available. Though, I know there are some PHP [...]]]></description>
			<content:encoded><![CDATA[	<p>One of the things I&#8217;ve always wanted to write, ever since I started writing web backends, is a proper extendable (plugin) framework in PHP. I&#8217;ve spent a little time searching for something that would fit my needs, but surprisingly there are very few free, documented plugin frameworks available. Though, I know there are some PHP applications out there that have very good backends (my favorite so far is <a href="http://gallery.menalto.com/">Gallery 2</a>), but they haven&#8217;t released the backend as a standalone package that is documented for others to write their own programs.</p>
	<p>A plugin framework is nothing new, as there have been many great minds who have worked on the subject, so I shouldn&#8217;t have to reinvent the wheel. I started my search with the well known <a href="http://eclipse.org">Eclipse</a>. After delving into the development docs, I found that Eclipse 3 is built on top of the <a href="http://www.osgi.org/osgi_technology/index.asp?section=2">OSGi framework</a> and <a href="http://jpf.sourceforge.net/"><acronym title="Java Plugin Framework">JPF</acronym></a>. So, delving in further, I read the spec on the OSGi framework and, after much thought, I believe it is possible to implement this framework in PHP and, at the same time, break new ground in PHP development by adding features that have never been done before (in PHP).<br />
<a id="more-12"></a></p>
	<h4>Goals</h4>
	<p>Some of the initial goals I had for a proper framework were:</p>
	<ul>
	<li>Universal</li>
	<li>Easy portablility of exisiting code</li>
	<li>Allows plugins lots of power, but in a controllable way</li>
	<li>Plugins should not have to be aware of other plugins it does not deal with</li>
	<li>Fast</li>
	<li>Dynamic</li>
	</ul>
	<p>The OSGi framework is a universal framework that allows for dynamic loading and unloading of code. It allows for the easy portability of existing code, and uses namespaces such that there are no name or resource collisions. Each plugin (bundle) has lots of power and flexability (providing a service offers it), but it is all controlled through the framework using services. The OSGi framework does have overhead, and can be quite slow when starting up, but if we can minimize the number of times the framework is started (cacheing, or keeping it running), then the only slow down is the advantages we get from using the framework.</p>
	<h4>Initial Problems</h4>
	<p>One of the problems with the OSGi framework, if you start reading it, is that it is designed for Java, and is based on a lot of high-level Java functions. Essentially they are three things that OSGi needs that Java has but PHP does not:</p>
	<ul>
	<li>Class loading</li>
	<li>Namespaces</li>
	<li>Advanced security</li>
	</ul>
	<p>The first one (class loading) is not much of an issue since we can import files that have class definitions in them. But what we can not do (easily) is enforce that only class definitions are loaded. Nor should we, as it breaks the very essence of PHP itself. However, we need to keep this in mind as we are implementing the framework for possible pitfalls (and security risks).</p>
	<p>The second problem, namespaces, is a very tricky one. One of the original goals of the OSGi framework is to load (or unload) bundles of code such that it does not affect other bundles unexpectedly. (Bundles should not need to be aware of other bundles) Unfortunately when PHP5 was designed, they ended up <a href="http://www.zend.com/zend/week/week140.php#Heading8">cutting out namespace support</a>. So what are we left with? Creating separate processes for each bundle isn&#8217;t the best answer since it will consume resources like mad, and sharing data would be a pain. However, threads uses very little additional memory, and allows for inter-thread communication easier. Now, unfortunately PHP does not have native thread support, but <a href="http://pecl.php.net/"><acronym title="PHP Extension Community Library">PECL</acronym></a>&#8217;s <a href="http://pecl.php.net/package/runkit">runkit package</a> supports sandboxed threads, and should be perfect for what we need to emulate the way Java implements namespaces. The sandboxing would also allow us to load code into each box without fear of it causing a collision in the main namespace. Also, runkit doesn&#8217;t completely isolate each thread from each other, as it provides mechanisms to communicate with the parent. Therefore, when we want to create a new namespace, we create a sandbox thread, initialize it with the environment we want, add functions that allow it to talk with other namespaces, and then load the user code. </p>
	<p>The other solution, as I have recently become aware, would be to use the supposed <a href="http://www.zend.com/zend/week/pat/pat44.txt">namespace patch</a> for PHP. However, there is apparently some <a href="http://www.zend.com/lists/engine2/200304/msg00164.html">big problems</a> with it and is likely not the best route to take until they are fixed and further integration is done.</p>
	<p>Lastly, PHP5 is sorely lacking security features. Sure there is <a href="http://ca.php.net/features.safe-mode">safe mode</a>, but its an all on/off solution and doesn&#8217;t allow for the fine grained control that the <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/spec/security-specTOC.fm.html">Java 2 Security Architecture</a> provides (which is optionally required by the OSGi framework). However, I believe that Java&#8217;s Security Architecture can be mimicked in PHP5 by using <a href="http://pecl.php.net/"><acronym title="PHP Extension Community Library">PECL</acronym></a>&#8217;s <a href="http://pecl.php.net/package/intercept">intercept package</a> (<a href="http://sumorai.net/s9y/archives/239-PHP-Intercept.html">doc</a>), <code>debug_backtrace()</code>, and code signing. Essentially, before loading any user code, we setup the environment such that we intercept any potentially dangerous system functions and, when called, code will check to see if the calling code (<code>debug_backtrace()</code>) has permission (using code signing) to run the requested function.</p>
	<p>Having identified and potentially eliminating the three biggest challenges, one problem remains - the user is required to install/patch at least two extensions to their PHP runtime engine. This is a problem because <em>a)</em> the user might not be able to because they are not admin or are using a pre-compiled package, or <em>b)</em> may conflict with other installed extensions. This problem could be simplified by writing a custom extension for the framework that implements all the desired features needed. But, unfortunately, there is no solution to this problem and is a consequence of using the framework.</p>
	<h4>Layers</h4>
	<p>The OSGi framework is defined as a layered structure. We too can also use this structure and add some other layers we need to setup PHP for the framework. The layers for this framework are listed below in an inverted order (bottom to top) and each layer&#8217;s code is able to access any other layers functions below it (providing it has the necessary permissions).</p>
	<h5>PHP5 w/ Extensions</h5>
	<p>This is a layer that we don&#8217;t necessarily need to do anything about. Its listed to hear to identify that PHP5 is required (for its class model, exceptions, etc.). The necessary extensions (runkit and intercept) should also be apart of this layer since they need to be compiled into PHP5 to improve the language enough so that we can do what we need to do.</p>
	<h5>PHP Environment Control</h5>
	<p>This layer is a required, simple abstraction layer/class for the compiled in extensions. It provides a standard API for easily accessing the necessary tasks that need to be performed with the compiled extensions. </p>
	<p>The purpose of this layer is to abstract the implementation details of the required extensions such that we could potentially use any extension that performed similar tasks (or new language constructs in PHP6), and all we would have to do is modify the abstraction layer. Also, in the future,  if a custom extension is written for this framework, it would have this API.</p>
	<h5>PHP5 Standardized API</h5>
	<p>This is a completely optional layer, but could bring some structure and help enforce good class-based API design. Essentially, this layer would implement the Java library in PHP. We would not, however, remove existing functions, but duplicate their functionality into a standardized API. </p>
	<p>For example:</p>
	<pre>
include(&#039;php/language/String&#039;);
&nbsp;
$comment = new String(&#039;This is a coment&#039;);
$comment.replace(&#039;coment&#039;, &#039;comment&#039;);
&nbsp;
echo $comment;
</pre>
	<p>There has already been some work on this done with the <a href="http://freshmeat.net/projects/japha/">Japha</a> project as it has implemented the most important parts of the Java Standard API already. However, some modification would be required such that we can now actually implement class (code) loading/namespaces.</p>
	<h5>PHP5 Security Architecture</h5>
	<p>This is an optional layer that allows for the locking down of the environment such that untrusted code is allowed to safely execute without fear of causing damage to the system. </p>
	<p>This is done by essentially mimicking the <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/spec/security-specTOC.fm.html">Java 2 Security Architecture</a>. Before any user code is loaded, we have a list of all known dangerous system functions, and the required permissions needed in order to access them. Then a parser runs through this list and adds intercepts (using <a href="http://pecl.php.net/"><acronym title="PHP Extension Community Library">PECL</acronym></a>&#8217;s <a href="http://pecl.php.net/package/intercept">intercept package</a>) to each dangerous function. The intercept, when fired, will check if the calling function (look at the stack with <a href="http://ca.php.net/debug_backtrace"><code>debug_backtrace()</code></a>) has the necessary permissions (using code signing and policies, discussed later) to run the requested function. If it does not, an exception is thrown.</p>
	<p>The <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/spec/security-specTOC.fm.html">Java 2 Security Architecture</a> does a good job defining how policies and code signing should work, so I won&#8217;t go into detail. But, an authority would need to be established in order to issue these certificates/policies in order for them to be enforceable. </p>
	<h5>OSGi Security Layer</h5>
	<blockquote><p>The OSGi Security Layer is an optional layer that underlies the OSGi Service Platform. The layer is based on the Java 2 security architecture. It provides the infrastructure to deploy and manage applications that must run in finegrained controlled environments.</p></blockquote>
	<p>Essentially, this layer adds extra security features to enhance Java&#8217;s own in order to take account the fact that there are code bundles now. When reading this doc, you will notice that it mentions about digital signed jar files a lot. Now, we could either use the <a href="http://software.zuavra.net/par/">PAR Loader</a> to implement this feature, or else we could just have digital signed directories of code that&#8217;s optionally installed using <a href="http://pear.php.net/">PEAR</a>.</p>
	<h5>OSGi Module Layer</h5>
	<blockquote><p>The standard Java platform provides only limited support for packaging, deploying, and validating Java-based applications and components. Because of this, many Java-based projects [&#8230;] have resorted to creating custom module-oriented layers with specialized class loaders for packaging, deploying, and validating applications and components. The OSGi Framework provides a generic and standardized solution for Java modularization.</p></blockquote>
	<p>This layer defines Bundles, how they are defined and how they work. I won&#8217;t go into much detail here since the specification does a great job at it already. Just replace the words &#8220;Java&#8221; with &#8220;PHP&#8221;, and its pretty easy to understand and create.</p>
	<h5>OSGi Life Cycle Layer</h5>
	<blockquote><p>The Life Cycle Layer provides an API to control the security and life cycle operations of bundles. [&#8230;] The Module Layer does not define how a bundle is installed, updated, and uninstalled. [The installation of a bundle can only be performed by another bundle.] These life cycle operations are defined here.</p></blockquote>
	<p>Without going into too much detail, this section defined the API that controls the basics of Bundle control. It also what happens when the framework is started/shutdown.</p>
	<h5>OSGi Service Layer</h5>
	<blockquote><p>The OSGi Service Layer defines a dynamic collaborative model that is highly integrated with the Life Cycle Layer. The service model is a publish, find and bind model. A service is a normal Java object that is registered under one or more Java interfaces with the service registry. Bundles can register services, search for them, or receive notifications when their registration state changes.</p></blockquote>
	<p>This is where our platform gets useful. The OSGi framework is built around services, each bundle having 0 to many services available, which are registered with the service registry defined in this layer.</p>
	<h5>Services</h5>
	<p>This layer is what adds the actual value to the framework and its purpose. Although any service could be defined depending the purpose of the application being written, the OSGi framework defines several universal/common services that should be implemented.</p>
	<dl>
	<dt>
<h6>OSGi Package Admin Service</h6>
</dt>
	<dd>
	<blockquote><p>Bundles can export packages to other bundles. This exporting creates a dependency between the bundle exporting a package and the bundle using the package. When the exporting bundle is uninstalled or updated, a decision must be taken regarding any shared packages. </p>
	<p>The Package Admin service provides an interface to let the Management Agent make this decision.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Start Level Service</h6>
</dt>
	<dd>
	<blockquote><p>This specification describes how to enable a Management Agent to control the relative starting and stopping order of bundles in an OSGi Service Platform. </p>
	<p>The Start Level service assigns each bundle a start level. The Management Agent can modify the start levels for bundles and set the active start level of the Framework, which will start and stop the appropriate bundles. Only bundles that have a start level less or equal to this active start level must be active.</p>
	<p>The purpose of the Start Level service is to allow the Management Agent to control, in detail, what bundles will be started and stopped and when this occurs.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Conditional Permission Admin Service</h6>
</dt>
	<dd>
	<blockquote><p>A key aspect of this security management API is the real time management of the permissions. This enables management applications to control the permissions of other applications with immediate effect; no restart is required.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Permission Admin Service</h6>
</dt>
	<dd>
	<blockquote><p>In the Framework, a bundle can have a single set of permissions. These permissions are used to verify that a bundle is authorized to execute privileged code. For example, a FilePermission defines what files can be used and in what way.</p>
	<p>The policy of providing the permissions to the bundle should be delegated to a Management Agent. For this reason, the Framework provides the Permission Admin service so that a Management Agent can administrate the permissions of a bundle and provide defaults for all bundles.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi URL Handlers Service</h6>
</dt>
	<dd>
	<blockquote><p>This specification is necessary because the standard Java mechanisms for extending the URL class with new schemes and different content types is not compatible with the dynamic aspects of an OSGi Service Platform. The registration of a new scheme or content type is a one time only action in Java, and once registered, a scheme or content type can never be revoked. This singleton approach to registration makes the provided mechanism impossible to use by different, independent bundles. Therefore, it is necessary for OSGi Framework implementations to hide this mechanism and provide an alternative mechanism that can be used.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Log Service</h6>
</dt>
	<dd>
	<blockquote><p>The Log Service provides a general purpose message logger for the OSGi Service Platform. It consists of two services, one for logging information and another for retrieving current or previously recorded log information.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Http Service</h6>
</dt>
	<dd>
	<blockquote><p>An OSGi Service Platform normally provides users with access to services on the Internet and other networks. This access allows users to remotely retrieve information from, and send control to, services in an OSGi Service Platform using a standard web browser.</p></blockquote>
	<p>I think this service could be the money maker for this framework. Essentially, you could create this service by modifying <a href="http://nanoweb.si.kz/">Nanoweb</a> to work as the HTTP server, then you could run this framework standalone (without Apache) and get an increase in PHP performance and control.</p>
	</dd>
	<dt>
<h6>OSGi Configuration Admin Service</h6>
</dt>
	<dd>
	<blockquote><p>The Configuration Admin service is an important aspect of the deployment of an OSGi Service Platform. It allows an Operator to set the configuration information of deployed bundles. </p>
	<p>Configuration is the process of defining the configuration data of bundles and assuring that those bundles receive that data when they are active in the OSGi Service Platform.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Preferences Service</h6>
</dt>
	<dd>
	<blockquote><p>Many bundles need to save some data persistently&#8211;in other words, the data is required to survive the stopping and restarting of the bundle, Framework and OSGi Service Platform. In some cases, the data is specific to a particular user. Some data is not specific to a user, which we call system data.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi User Admin Service</h6>
</dt>
	<dd>
	<blockquote><p>OSGi Service Platforms are often used in places where end users initiate actions. These kinds of actions inevitably create a need for authenticating the initiator. Authenticating can be done in many different ways, including with passwords, one-time token cards, bio-metrics, and certificates. Once the initiator is authenticated, it is necessary to verify that this principal is authorized to perform the requested action. This authorization can only be decided by the operator of the OSGi environment, and thus requires administration. The User Admin service provides this type of functionality.</p></blockquote>
	<p>Another important feature of this framework as it allows for a single, powerful, and standardized authentication system for the framework across multiple different application.</p>
	</dd>
	<dt>
<h6>OSGi Event Admin Service</h6>
</dt>
	<dd>
	<blockquote><p>The Event Admin service provides an inter-bundle communication mechanism. It is based on a event publish and subscribe model, popular in many message based systems.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Service Tracker Service</h6>
</dt>
	<dd>
	<blockquote><p>The specification defines a utility class, ServiceTracker, that makes tracking the registration, modification, and unregistration of services much easier. A ServiceTracker class can be customized by implementing the interface or by sub-classing the ServiceTracker class.</p></blockquote>
	</dd>
	<dt>
<h6>OSGi Declarative Services</h6>
</dt>
	<dd>This service is a bit complicated in its definition, but basically provides a method of adding services that do not have to worry about services it depends on being active, and will only cause the framework to only load services when needed (reducing footprint and startup time).</dd>
	</dl>
	<p>There are various other services that the OSGi specification specifies. The ones not listed here are not likely needed for a PHP environment. (Unless say it was the only application running on a dedicated hardware device)</p>
	<h4>Usage</h4>
	<p>This is how I envision the framework being use; The application using the framework is designed to be run standalone and runs like a daemon process. At startup, it loads all the neccessary services (including the HTTP service) and then the application service. The application service controls a blog that is displayed (and receives feedback) from the HTTP Service. It also provides an admin interface for allowing the loading of plugins. These plugins are loaded/unloaded/updated at runtime and the framework never has to shutdown. Because the PHP code is loaded into memory and stays, the running of PHP code is fast and results come back quick.</p>
	<h4>Conclusion</h4>
	<p>Although a framework like this would be a tremendous undertaking (not including any applications built on top of it), I believe that this would get a lot of media attention and cause several preexisiting apps to be ported to the framework and, consequently, allow for the easy mashup of various services. And why not? Most pre-exisiting applications would only require a manifest and class loader file, and they could be run by the application without worry of namespace collisions. This could also breathe some new life into PHP development.</p>
	<p>Now, having said <strong>all</strong> of this, none of this has been tested. This is purely a concept idea and may actually not be possible. My biggest concerns are, in fact, the two required extensions and if they can be loaded together and are able to perform a good enough job for what is needed. Having said that, a custom extension could (and eventually should) be written to handle the necessary limitations of PHP.</p>
	<p>Now, I know a lot of people oppose the whole &#8220;PHP should not try to be like Java&#8221; bit, but Java has some really nice features, and combining those with PHP&#8217;s really nice features, we could create something better then the both of them. Just my opinion on it.</p>
	<p>If anyone is interested in working on a framework like this, please feel free to <a href="http://garycourt.com/contact/">contact me</a> or <a href="#respond">leave a message in the comments</a>.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/php-osgi-framework-concept/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>AWStats on Debian</title>
		<link>http://garycourt.com/blog/post/awstats-on-debian/</link>
		<comments>http://garycourt.com/blog/post/awstats-on-debian/#comments</comments>
		<pubDate>Fri, 20 Jan 2006 19:36:13 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Linux</category>
	<category>Tutorial</category>
		<guid>http://garycourt.com/blog/post/awstats-on-debian/</guid>
		<description><![CDATA[	I was looking for a good traffic analyzer for my website when I came across AWStats. It looked good compared to other log analyzers, so I decided to give it a try. I&#8217;m a fan of the Debian operating system, which I use on most of my servers. So, like any typical Debian user, I [...]]]></description>
			<content:encoded><![CDATA[	<p>I was looking for a good traffic analyzer for my website when I came across <a href="http://www.awstats.org/">AWStats</a>. It looked good <a href="http://awstats.sourceforge.net/docs/awstats_compare.html">compared to other log analyzers</a>, so I decided to give it a try. I&#8217;m a fan of the <a href="http://www.debian.org/">Debian</a> operating system, which I use on most of my servers. So, like any typical Debian user, I used the package management system (<a href="http://www.debian.org/doc/manuals/apt-howto/index.en.html">APT</a>) to install AWStats. Normally the Debian packages are pretty good for doing everything automatically for you, but not so with the AWStats package - which required some setting up. For those wanting to go this route, this is how you get <a href="http://packages.debian.org/stable/web/awstats">AWStats&#8217; Debian package</a> to work with <a href="http://httpd.apache.org/">Apache</a>.<br />
<a id="more-11"></a></p>
	<h4>Install AWStats</h4>
	<p>Start off by installing the AWStats package using APT.</p>
	<pre>
apt-get install awstats
</pre>
	<p>After installation, everything you need for AWStats can be found in the following directories:</p>
	<dl>
	<dt><code>/etc/awstats/</code></dt>
	<dd>Configuration files for AWStats.</dd>
	<dt><code>/usr/share/awstats/</code></dt>
	<dd>Runtime libraries, plugins, language files, and icons.</dd>
	<dt><code>/usr/share/doc/awstats/</code></dt>
	<dd>README on how to setup AWStats. Consult if you are having problems.</dd>
	<dt><code>/usr/share/doc/awstats/examples/</code></dt>
	<dd>Setup and configuration scripts. If your looking for a script mentioned in the official docs, chances are it is here.</dd>
	<dt><code>/usr/lib/cgi-bin/</code></dt>
	<dd>Contains <code>awstats.pl</code>, the program itself.</dd>
	</dl>
	<h4>Setup Apache</h4>
	<p>First thing that needs to be done is to setup Apache&#8217;s logging appropriately. I use <a href="http://httpd.apache.org/">Apache 2</a> on my server, so this article will be focused towards it.</p>
	<p>Ensure that Apache is in fact logging access requests. For each virtual host (found in <code>/etc/apache2/sites-enabled/</code>), make sure there is something like the following present: (replace <code>example.com</code> with the virtual host domain name)</p>
	<pre>
CustomLog /var/log/apache2/access.example.com.log combined
</pre>
	<p>You can also check the main configuration file (<code>/etc/apache2/apache2.conf</code>) to see if a global <code>CustomLog</code> is specified, however, it is recommended that you create a log for each individual domain name. In any case, make sure that the last parameter of <code>CustomLog</code> is <code>combined</code> as it will help AWStats produce better results. (Note: that if you already have a <code>CustomLog</code> directive in your configuration file that uses something else other then <code>combined</code>, please delete the already pre-existing log files.)</p>
	<p>Before we are done, copy <code>/usr/share/doc/awstats/examples/apache.conf</code> to <code>/etc/apache2/conf.d/awstats.conf</code>. This will setup the necessary aliases to access AWStats from the web (on all virtual hosts). If you would like to control which virtual hosts will have these aliases specified, then copy the code within <code>apache.conf</code> into a virtual host definition:</p>
	<pre>
# This provides worldwide access to everything below the directory
&lt;directory /var/lib/awstats&gt;
        Options None
        AllowOverride None
        Order allow,deny
        Allow from all
&lt;/directory&gt;
&nbsp;
# This provides worldwide access to everything below the directory
&lt;directory /usr/share/awstats/icon&gt;
        Options None
        AllowOverride None
        Order allow,deny
        Allow from all
&lt;/directory&gt;
&nbsp;
# This provides worldwide access to everything in the directory
Alias /awstats-icon/ /usr/share/awstats/icon/
&nbsp;
# This (hopefully) enables _all_ CGI scripts in the default directory
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
</pre>
	<p>Don&#8217;t forget to restart Apache when your done:</p>
	<pre>
/etc/init.d/apache2 restart
</pre>
	<h4>Setup AWStats</h4>
	<p>Next step is to setup the AWStats configuration files. In <code>/etc/awstats/</code>, you will see the file <code>awstats.conf</code>. It is recommended that you setup a configuration file for each virtual host that you want to monitor. To do this, copy <code>awstats.conf</code> to <code>awstats.example.com.conf</code>. (Replacing <code>example.com</code> with your domain name.) Next, go through <code>awstats.example.com.conf</code> and customize it for your site. The critical options to change are:</p>
	<pre>
#Log file for virtual domain
LogFile=&quot;/var/log/apache2/access.example.com.log&quot;
&nbsp;
#Log type: Web
LogType=W
&nbsp;
#Apache or Lotus Notes/Domino native combined log format (NCSA combined/XLF/ELF log format)
LogFormat=1
&nbsp;
#Main domain name used to reach website. Used for log parsing (skipping) and server-side link generation.
SiteDomain=&quot;example.com&quot;
&nbsp;
#Other domain names that can be used to access web site. This example uses a regular expression to reduce typing.
HostAliases=&quot;REGEX[(www\.)?example\.(com|net|org)$]&quot;
</pre>
	<h4>Testing</h4>
	<p>We can now generate statistics for your website by running AWStats:</p>
	<pre>
/usr/lib/cgi-bin/awstats.pl -config=example.com -update
</pre>
	<p>Which should output something like:</p>
	<pre>
Update for config &quot;/etc/awstats/awstats.example.com.conf&quot;
With data in log file &quot;/var/log/apache2/access.example.com.log&quot;&#46;..
Phase 1 : First bypass old records, searching new record&#46;..
Parsed lines in file: 5
 Found 0 dropped records,
 Found 0 corrupted records,
 Found 0 old records,
 Found 5 new qualified records.
</pre>
	<p>Providing there are no errors, we can view the results by pointing our web browser to:</p>
	<pre>
http://example.com/cgi-bin/awstats.pl?config=example.com
</pre>
	<h4>Automation</h4>
	<p>At the moment, statistics will only be generated when you run the script manually. Therefore, lets automate it as a <a href="http://en.wikipedia.org/wiki/Cron">cron</a> job. In <code>/etc/cron.d/</code> there will already be a file called <code>awstats</code>. Theoretically you should be able to edit this file and change the part <code>-config=</code>, but I couldn&#8217;t get this to work. So, I wrote my own which I find works for me. If you&#8217;d like to do the same, replace the content of <code>awstats</code> with:</p>
	<pre>
0 * * * * www-data /usr/lib/cgi-bin/awstats.pl -config=example.com -update &gt;/dev/null
</pre>
	<p>This code will cause your statistics to be generated every hour.</p>
	<p>Now, there&#8217;s one small problem with this. For anyone familiar with Apache, you know that, by default, the Apache logs are rotated (to prevent them from getting to big) . This causes a problem that if entries to the logs are made between awstats running and the logs rotated, those entries are lost. Therefore, we need to modify <code>/etc/logrotate.d/apache2</code>, and add some <code>prerotate</code> code:</p>
	<pre>
/var/log/apache2/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 644 root adm
        sharedscripts
        prerotate
                /usr/lib/cgi-bin/awstats.pl -config=example.com -update
        endscript
        postrotate
                if [ -f /var/run/apache2.pid ]; then
                        /etc/init.d/apache2 restart &gt; /dev/null
                fi
        endscript
}
</pre>
	<p>The changes I have made are:</p>
	<ul>
	<li>Added the prerotate section:
	<pre>
prerotate
        /usr/lib/cgi-bin/awstats.pl -config=example.com -update
endscript
</pre>
	</li>
	<li>Changed the permissions on the log files:
	<pre>
create 644 root adm
</pre>
	</li>
	</ul>
	<p>Note that the permission change is to allow the cron job (running as user <code>www-data</code>) to access the log files. (This is the lazy way) If you already have pre-existing log files, you can change their permission by running:</p>
	<pre>
chmod o+r /var/log/apache2/*.log
</pre>
	<p>If you don&#8217;t want to allow all users read access to the log files, then you can try changing the group owner on the log files to <code>www-data</code>. (I haven&#8217;t tried this, so no guarantee it will work)</p>
	<h4>Conclusion</h4>
	<p>There we have it, getting AWStats to run on Debian. One of the things I would recommend, before leaving this, is to secure the the generated results with a username and password (using Apache&#8217;s <a href="http://httpd.apache.org/docs/2.0/howto/auth.html"><code>mod_auth</code></a>). Although it is out of the scope of this article, if you would like me to go about showing you, please mention in the comments.</p>
	<p>For more information on AWStats configuration options and abilities, please see their <a href="http://awstats.sourceforge.net/docs/index.html">official documentation</a>.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/awstats-on-debian/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Latest Gallery pictures in WordPress</title>
		<link>http://garycourt.com/blog/post/latest-gallery-pictures-in-wordpress/</link>
		<comments>http://garycourt.com/blog/post/latest-gallery-pictures-in-wordpress/#comments</comments>
		<pubDate>Tue, 17 Jan 2006 00:46:23 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Web Development</category>
	<category>PHP</category>
	<category>WordPress</category>
		<guid>http://garycourt.com/blog/post/latest-gallery-pictures-in-wordpress/</guid>
		<description><![CDATA[	One of the things I wanted to do when integrating Gallery 2 into WordPress (using the WPG2 plugin) was to be able to see, on the main page, all the latest pictures posted in my gallery. The WPG2 plugin only supported displaying the last item added, and I could not find anyone else to have [...]]]></description>
			<content:encoded><![CDATA[	<p>One of the things I wanted to do when integrating <a href="http://gallery.menalto.com/">Gallery 2</a> into <a href="http://wordpress.org/">WordPress</a> (using the <a href="http://wpg2.ozgreg.com/">WPG2 plugin</a>) was to be able to see, on the main page, all the latest pictures posted in <a href="http://garycourt.com/gallery/">my gallery</a>. The WPG2 plugin only supported displaying the last item added, and I could not find anyone else to have done this. So, I wrote up a quick hack to perform this function. It&#8217;s not pretty, but it does the job. Feel free to use it for your own site.<br />
<a id="more-10"></a><br />
In order to display the latest items added to your gallery, paste this code in your theme where you want it to be displayed. You can specify how far you want to go back by changing <code>$gc_item_limit</code>.</p>
	<pre>
//Find the latest Gallery pictures
$gc_item_limit = 4;  //number of items to display
$gc_connection = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD) or die(&quot;Can&#039;t connect to DB Server.&lt;br /&gt;&quot;.mysql_error());
$gc_dbconnection = mysql_select_db(DB_NAME, $gc_connection) or die(&quot;Can&#039;t connect to DB.&lt;br /&gt;&quot;.mysql_error());
$gc_run = &#039;SELECT g_id FROM g2_Item WHERE g_canContainChildren = 0 ORDER BY g_id DESC LIMIT &#039;.$gc_item_limit;
$gc_result = mysql_query($gc_run);
if (mysql_num_rows($gc_result) &lt; 1)
  echo &#039;&lt;p&gt;No Pictures Found&lt; /p&gt;&#039;;
while ($row = mysql_fetch_array($gc_result, MYSQL_ASSOC)) {
  $gc_imageblock = g2_imageblock($row[&#039;g_id&#039;], 120);
  $gc_imageblock = str_replace(&#039;id=&quot;g2content&quot;&#039;, &#039;&#039;, $gc_imageblock);
  echo $gc_imageblock;
}
mysql_free_result($gc_result);
</pre>
	<p>You can see this code in action on <a href="http://garycourt.com/">my index page</a>.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/latest-gallery-pictures-in-wordpress/feed/</wfw:commentRSS>
	</item>
		<item>
		<title>Poplars</title>
		<link>http://garycourt.com/blog/post/poplars/</link>
		<comments>http://garycourt.com/blog/post/poplars/#comments</comments>
		<pubDate>Wed, 11 Jan 2006 20:29:44 +0000</pubDate>
		<dc:creator>Gary Court</dc:creator>
		
	<category>Games</category>
	<category>Windows</category>
		<guid>http://garycourt.com/blog/post/poplars/</guid>
		<description><![CDATA[	Poplars is a turn-based strategy game that is traditionally played on a 6&#215;5 board with two opponents. (You can, however, play on any sized board with up to four players optionally) It is a game for all ages that requires recursive thinking and good foresight. Poplars is a game of position and territory that requires [...]]]></description>
			<content:encoded><![CDATA[	<p><img class="alignRight" src='/wp-content/images/thumb-poplarsScreen.png' alt='Poplars' /><strong>Poplars</strong> is a turn-based strategy game that is traditionally played on a 6&#215;5 board with two opponents. (You can, however, play on any sized board with up to four players optionally) It is a game for all ages that requires recursive thinking and good foresight. Poplars is a game of position and territory that requires pure skill (as are other games such as go, chess, and tic-tac-toe). The object of the game is to completely own every square that contains a Poplar without letting the opponent do the same.<br />
<a id="more-9"></a><br />
Poplars was completely developed by myself (<a href="http://garycourt.com/about/">Gary Court</a>) in my second year of university (March, 2002) for a class project. It is written in <a href="http://en.wikipedia.org/wiki/C++">C++</a> &#038; <a href="http://en.wikipedia.org/wiki/Microsoft_Foundation_Classes">MFC</a>, and should work on virtually any version of Windows (since &#8216;98). It is based on the game <a href="http://www.cs.umanitoba.ca/~zapp/Palm/">Critical Mass</a>, which happens to have been developed by one of my professors.</p>
	<p>The game is played by placing Poplars on the board one at a time. Each spot on the board can only hold a limited number of Poplars (determined by the number of adjacent spaces), and when that spot is filled, it will &#8220;pop&#8221; and spread the Poplars to the adjacent spaces. However, the consequence of &#8220;popping&#8221; a space is that it may cause a subsequent space to be full creating a chain reaction of multiple spaces &#8220;popping&#8221;.</p>
	<p>The game can be played with two to four players, human or computer, on any sized board. There are 5 skills levels (including a training level), undo move feature, and quick tip (for those who are stuck).</p>
	<p>This was one of my most interesting projects in university at the time as it exposed me to such new concepts as game development, C++, MFC, Windows development, GUI development, artificial intelligence design, and usability design. I received an A+ for the project and the course, and won the unofficial award of Best Game of the Class.</p>
	<p>For more information on Poplars and how to play it, please see the included help file.</p>
	<div class="download-box"><a href="/wp-content/files/Poplars.zip" title="Download Poplars"><img src="/wp-content/images/poplarsLogo.gif" alt="*" />
<p>Download Poplars</p>
</a></div>
]]></content:encoded>
			<wfw:commentRSS>http://garycourt.com/blog/post/poplars/feed/</wfw:commentRSS>
	</item>
	</channel>
</rss>
