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

<channel>
	<title>james coletti</title>
	<atom:link href="http://jamescoletti.com/feed" rel="self" type="application/rss+xml" />
	<link>http://jamescoletti.com</link>
	<description>At least you'll learn something.</description>
	<pubDate>Sun, 04 Jan 2009 01:28:40 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP website monitoring script</title>
		<link>http://jamescoletti.com/php-website-monitoring-script</link>
		<comments>http://jamescoletti.com/php-website-monitoring-script#comments</comments>
		<pubDate>Sun, 04 Jan 2009 01:27:24 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[administration]]></category>

		<category><![CDATA[monitoring]]></category>

		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://jamescoletti.com/?p=114</guid>
		<description><![CDATA[If you run a web server or two, hosting several websites and you're in need of a way to be alerted when one or more sites break, this script might help you out.]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a handy script (called &#8220;sPing&#8221;) to monitor any number of sites and ensure that they return a pleasant status code (200 or 304). The script will silently access each of the URLs in the array. Any that return something nasty like a 403, 404, 500, or 503 will be output to the console along with the particular status code.</p>
<p><strong>sping.php</strong></p>
<pre class="syntax-highlight:php">
&lt;?php

/* -------- Configuration -------- */

define(&#039;VERSION&#039;, &#039;1.0&#039;);

define(&#039;USERAGENT&#039;, &#039;sPing/&#039;.VERSION);
define(&#039;TIMEOUT&#039;, 10); // seconds

$sites = array(
   &#039;http://www.site1.com&#039;,
   &#039;http://www.site2.com&#039;,
   &#039;http://www.site3.com&#039;,
);

/* ------------------------------- */

if ( ! function_exists(&#039;curl_init&#039;)) { die(&quot;cURL is not available and is required.n&quot;); }

$ch = curl_init();

$options = array(
   CURLOPT_USERAGENT =&gt; USERAGENT,
   CURLOPT_TIMEOUT =&gt; TIMEOUT,
   CURLOPT_VERBOSE =&gt; false,
   CURLOPT_RETURNTRANSFER =&gt; true,
   CURLOPT_FRESH_CONNECT =&gt; true
);

curl_setopt_array($ch, $options);

foreach($sites as $site)
{
   curl_setopt ($ch, CURLOPT_URL, $site);
   $output = curl_exec($ch);

   $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);

   if ($status != 200 &amp;&amp; $status != 304)
   {
      echo $site.&quot; returned &quot;.$status.&quot;n&quot;;
   }
}
</pre>
<p>You can customize the maximum allowed timeout (in seconds) and the user agent used when making the request. I use a unique user agent so I can track and exclude requests from this script in web server logs &#038; statistics.</p>
<p>This script works best when run periodically via <strong>cron</strong> and piping the output to <strong>mail</strong> with the <strong>-e</strong> parameter. This tells mail only to send an e-mail if the message body is not null (meaning that one of the sites is acting up, the script produced output, and we want to know about it).</p>
<pre>
./sping.php | /usr/bin/mail -e -s "[`hostname`] Abnormal HTTP statuses" alerts@mydomain.com
</pre>
<p>Lastly, while you CAN run this script on the same server where the sites live (for catching things like syntax errors introduced by your team mate, hacking up files at 4 AM, or memory issues that might cause your sites to blank screen), it makes more sense to run this on a second, stable server with 24/7 connectivity in case the server completely crashes. It&#8217;s most effective to monitor from the view of the public (the &#8220;visitor&#8221; or the &#8220;customer&#8221;).</p>
]]></content:encoded>
			<wfw:commentRss>http://jamescoletti.com/php-website-monitoring-script/feed</wfw:commentRss>
		</item>
		<item>
		<title>Simple WordPress contact form plugin!</title>
		<link>http://jamescoletti.com/simple-wordpress-contact-form-plugin</link>
		<comments>http://jamescoletti.com/simple-wordpress-contact-form-plugin#comments</comments>
		<pubDate>Thu, 01 Jan 2009 01:52:09 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[WordPress]]></category>

		<category><![CDATA[plugins]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://jamescoletti.com/?p=96</guid>
		<description><![CDATA[Yes, that's right. Another WordPress Contact Form plugin, made to be simple, lightweight and reliable.]]></description>
			<content:encoded><![CDATA[<p>Oh no, not another &#8220;simple wordpress contact form&#8221;. Yes, that&#8217;s right. There are a million contact form plugins for WordPress, and I&#8217;ve probably tried the majority of them. They&#8217;re great, don&#8217;t get me wrong, but either they&#8217;re bloated with features that I don&#8217;t use or I&#8217;m just O.C.D. about certain things. Hence, I have crafted my own and made it available for download in the event that others may find it useful, too.</p>
<h3>Features</h3>
<ul>
<li>Simple to install and easy to configure via an Admin options page.</li>
<li>Ability to set a destination e-mail address where submissions will be delivered. (If one is not set or an error occurs, submissions are logged to the web server&#8217;s error log.)</li>
<li>Ability to configure an optional list of subjects to be displayed to the user in a drop-down. (If subjects are not configured, the drop-down is hidden.)</li>
<li>Lightweight and contained in a single file.</li>
<li>Secure. Malicious code from nasty users within submissions will be stripped away before hitting your inbox.</li>
<li>Compatible with WordPress 2.x, including 2.7!</li>
</ul>
<h3>How to Install</h3>
<ol>
<li>Extract the .zip archive to your wp-content/plugins directory.</li>
<li>Activate the plugin in the Admin panel.</li>
<li>Configure the options on the &#8220;Contact Form&#8221; page under &#8220;Settings&#8221;.</li>
<li>Add the &#8220;&#91;contactform&#93;&#8221; shortcode to any of your pages, and voila!</li>
</ol>
<h3>Download</h3>
<ul>
<li><a title="FTN Contact Form" href="http://jamescoletti.com/wp-content/downloads/ftn_contactform_v1.0.zip">FTN Contact Form v1.0</a></li>
</ul>
<h3>Styling</h3>
<p><em>&#8220;Wait! My form and error messages look ugly!&#8221;</em></p>
<p>OK, so style them. Try something like this:</p>
<pre class="syntax-highlight:css">
/* FTN Contact Form */
#ftn_contactform ul {list-style-type:none; padding-left:0;}
#ftn_contactform ul li {margin-bottom:6px;}
#ftn_contactform label {display:block; font-weight:bold; font-size:12px;}
#ftn_contactform .textbox {padding:4px; border:1px solid #ccc; width:300px;}
#ftn_contactform textarea.textbox {height:150px; width:400px;}

/* Generic errors and info messages */
div.msg {margin-bottom:20px; padding:10px;}
div.msg ul {padding:0; margin:0 0 0 20px;}

div.errormsg {background:#ffffe5; border:1px solid #ffe5b2;}
div.errormsg em {font-style:normal; color:#d74117; font-weight:bold;}
div.errormsg ul {padding:8px 0 0 20px; margin:0;}

div.successmsg {font-weight:bold; background:#f4f9f2; border:1px solid #A8CF9B; color:#5A8F47;}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jamescoletti.com/simple-wordpress-contact-form-plugin/feed</wfw:commentRss>
		</item>
		<item>
		<title>Multiple WordPress installs and object cache collision</title>
		<link>http://jamescoletti.com/multiple-wordpress-installs-and-object-cache-collision</link>
		<comments>http://jamescoletti.com/multiple-wordpress-installs-and-object-cache-collision#comments</comments>
		<pubDate>Sun, 21 Dec 2008 06:23:50 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[WordPress]]></category>

		<category><![CDATA[apc]]></category>

		<category><![CDATA[caching]]></category>

		<category><![CDATA[wpmu]]></category>

		<category><![CDATA[xcache]]></category>

		<guid isPermaLink="false">http://jamescoletti.com/?p=69</guid>
		<description><![CDATA[Are you using multiple installations of WordPress on the same server and experiencing strange behavior with user caches? Read on...]]></description>
			<content:encoded><![CDATA[<p>I have a fairly sophisticated WordPress setup where every site has its own database, shares a common regular WordPress 2.7 code base, can optionally share themes and plugins, and much more. (Yes, this is all done without hacking any of the core files so upgrades aren&#8217;t a nightmare.) There are several reasons this works for me over <a title="WordPress MU" href="http://mu.wordpress.org" target="_blank">WordPress MU</a>, but that is beyond the scope of this post. In either case, I wanted to reduce the load on the MySQL servers by caching data objects. I was already using <a title="Alternative PHP Cache" href="http://pecl.php.net/package/APC/" target="_blank">APC</a> as an opcode cache, but I started hearing great things about <a title="XCache" href="http://xcache.lighttpd.net/" target="_blank">XCache</a> and decided it might be a good time to give XC a whirl too.</p>
<p>After looking at several WordPress object cache backends I stumbled across Dougal Campbell&#8217;s <a title="XCache Object Cache for WordPress" href="http://dougal.gunters.org/blog/2008/08/29/xcache-object-cache-plugin-for-wordpress-25" target="_blank">XCache Object Cache Plugin for WordPress 2.5+</a>, which seems to be the best one out there. There&#8217;s only one major issue with it: <strong>it always assumes that user data should be shared</strong>.</p>
<p>I&#8217;m not sure if this is a bug or an attempted enhancement, though I&#8217;ve read about several people experiencing the same issues as I was upon first installation. This issue is present in the current, latest version of the plugin, 0.7d.</p>
<p>In my particular environment, I use the same WordPress code to power completely unique and independent websites. I don&#8217;t want them sharing <strong>any</strong> data between databases. Dougal&#8217;s clever plugin prefixes each cache key with the site&#8217;s database name constant and blog_id (for WPMU) to make this happen. Sort of. For example, a particular post&#8217;s cache key might look something like:</p>
<p><code>my_db_name:wp_1:posts:19</code></p>
<p>Great, right? This seems to work in every case except for user data (&#8217;users&#8217;, &#8216;usermeta&#8217; and &#8216;userlogins&#8217;). The cache keys are not prefixed and therefore sites are clobbering each others&#8217; user caches, or possibly reading user caches that belong to another site! Not good. This is clearly a problem when attempting to log into site A&#8217;s administration panel, receiving an &#8216;incorrect username or password&#8217; message, but having it happily accept credentials from site B&#8217;s database.</p>
<p>The solution?</p>
<p>Replace line 191 in version 0.7d of &#8220;object-cache.php&#8221;, which originally reads:</p>
<pre class="syntax-highlight:php">
if (false !== array_search($group, $this-&gt;global_groups))
</pre>
<p>with the line:</p>
<pre class="syntax-highlight:php">
if (defined(&#039;VHOST&#039;) &amp;&amp; false !== array_search($group, $this-&gt;global_groups))
</pre>
<p>And voila, ALL of your cache keys will be properly prefixed. Since WPMU uses virtual host magic to do its sub-domain routing, checking whether the VHOST constant is defined is a great way to determine if the WordPress version is infact WPMU. In the revised code, if the particular site is using a plain old vanilla WordPress install, we probably don&#8217;t want to share any data so might as well save ourselves a call to array_search() and ALWAYS prefix the cache key.</p>
<p>Thanks Dougal for a great object cache backend and hopefully this post helps clear up issues that other users may be experiencing. It&#8217;s also worth pointing out that most of the other backends out there don&#8217;t even prefix the keys, which creates a huge mess in cases like mine. Dougal&#8217;s elegant approach is also available for APC and eAccelerator I think.</p>
<p>XCache seems to be slightly outperforming APC at a quick glance and I haven&#8217;t had a chance to really tune it yet. I&#8217;m hoping to get some concrete stats up in the near future.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamescoletti.com/multiple-wordpress-installs-and-object-cache-collision/feed</wfw:commentRss>
		</item>
		<item>
		<title>RouterBOARD RB532 assembly and configuration tutorial</title>
		<link>http://jamescoletti.com/routerboard-rb532-assembly-and-configuration-tutorial</link>
		<comments>http://jamescoletti.com/routerboard-rb532-assembly-and-configuration-tutorial#comments</comments>
		<pubDate>Thu, 11 Dec 2008 06:23:11 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[Networking]]></category>

		<category><![CDATA[Tutorials]]></category>

		<category><![CDATA[router]]></category>

		<category><![CDATA[routerboard]]></category>

		<guid isPermaLink="false">http://jamescoletti.com/?p=48</guid>
		<description><![CDATA[In-depth tutorial on how to build and configure a RouterBOARD RB532A router from MikroTik. Home/office DIY network folk should enjoy.]]></description>
			<content:encoded><![CDATA[<p>So the site has been dying for some new content, and I haven’t had five minutes to conjure up anything. Coincidentally, my old <a title="Netgear RT311 Review at PracticallyNetworked" rel="nofollow" href="http://www.practicallynetworked.com/review.asp?pid=318" target="_blank">Netgear RT311</a> router started acting up and my replacement solution turned into a small project, and from it I created this tutorial.</p>
<h3>Unpacking and Examination</h3>
<p>I ordered the <a title="RouterBoard 532A at Titan Wireless Online" href="http://www.titanwirelessonline.com/ProductDetails.asp?ProductCode=RB%2D532A" target="_blank">RouterBOARD 532A</a> (R5 series) CPU board, the <a title="RB532 enclosure at Titan Wireless Online" href="http://www.titanwirelessonline.com/ProductDetails.asp?ProductCode=EN%2DRBSM%2DI" target="_blank">RB532</a> matching metal enclosure with 2 holes for external swivel antennas (for later wireless expansion), and the two-part, <a title="18V Power Supply at Titan Wireless Online" href="http://www.titanwirelessonline.com/ProductDetails.asp?ProductCode=PE%2D18VS%2D1" target="_blank">18V power supply</a> all from <a title="Visit the Titan Wireless website" rel="nofollow" href="http://www.titanwirelessonline.com" target="_blank">Titan Wireless, LLC</a> for a grand total of $224.45. Doesn’t mean you need to spend this much, I happened to buy the Ferrari of CPU boards. There are cheaper <a title="View the various RouterBOARD products at routerboard.com" href="http://routerboard.com/comparison.html" target="_blank">RouterBOARD models</a> which are more than suitable for any home or office network. There’s also a software license factored into the price; more about this later. A quick word about Titan Wireless: I placed the order on a Monday with standard shipping and it shipped same-day within 4 hours, along with a confirmation e-mail and UPS tracking number. Each item came meticulously bubble-wrapped and everything looking mint. I definitely recommend this company for extremely fast service, quality, and prices (no I’m not affiliated).</p>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_unboxing.jpg"><img class="aligncenter size-medium wp-image-50" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_unboxing-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>The 532A differs from the straight 532 in that it has double the RAM (64MB vs. 32) and double the on-board NAND storage (128MB vs. 64). If you’re looking to buy this model, make sure you’re getting the R5 series. These are already running at the max 400 MHz, whereas previous versions come stock at 266 MHz, but can be changed. I chose this model because it won’t be limiting as I scale out its responsibilities and services, and the network and pipe size… and because I don’t want to buy another one any time soon. Your needs may be different. Let’s look at some of the 532A’s specs (adapted from the User’s Guide):</p>
<ul>
<li><strong>CPU</strong>: MIPS32 4Kc based 400MHz embedded processor</li>
<li><strong>Memory</strong>: 64MB DDR on-board memory</li>
<li><strong>Boot loader</strong>: RouterBOOT, 1Mbit flash chip</li>
<li><strong>Storage</strong>: 128MB on-board NAND memory and the ability to add a CompactFlash type I/II card (including IBM/Hitachi Microdrives)</li>
<li><strong>Ethernet</strong>: (1) IDT Korina 10/100 Mbit/s Fast Ethernet port supporting Auto-MDI/X, and (2) VIA VT6105 10/100 Mbit/s Fast Ethernet ports supporting Auto-MDI/X</li>
<li><strong>Expansion</strong>: Two MiniPCI Type IIIA/IIIB slots, and a RouterBOARD daughterboard socket</li>
<li><strong>Serial port</strong>: One DB9 RS232C asynchronous serial port</li>
<li><strong>LEDs</strong>: Power, 2 LED pairs for MiniPCI slots, 1 user LED</li>
<li><strong>Speaker</strong>: Mini PC-Speaker</li>
<li><strong>Power</strong>: IEEE802.3af Power over Ethernet: 12V or 48V DC mode and a power jack 6..22V (with overvoltage protection) or 25..60V DC – jumper selectable</li>
<li><strong>Dimensions</strong>: 14.0 cm x 14.0 cm (5.51 in x 5.51 in)</li>
</ul>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_board.jpg"><img class="aligncenter size-medium wp-image-51" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_board-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>In a nutshell, this thing is tiny but packs a lot of power: fast processor with generous memory and on-board storage, three Ethernet interfaces with one supporting Power-over-Ethernet (PoE), two MiniPCI slots for adding wireless cards and other devices, a serial port for direct access to the console and basically a way to bail you out in case you did something stupid like disabled all the Ethernet ports by accident or added an overly restrictive firewall rule, and a whole lot more. It’s worth pointing out that many distributors say the PoE port will not do power over data lines, but in fact the R5 series board does! You might also wonder what three Ethernet interfaces can do for you. Consider these configuration options:</p>
<ul>
<li>Configure 1 wide area network (WAN) port, and 2 local area network (LAN) ports: use your WAN port to connect you to the Internet, and your two LAN ports to segment your network: one network for users, and one for servers or a testbed for network projects.</li>
<li>Two WAN ports, and one LAN port: two WAN ports can connect your LAN to two providers (e.g. 2 distinct DSL connections) for redundancy at home or at the office.</li>
</ul>
<p>Okay, enough about features and possibilities. Let’s get it running…</p>
<h3>Assembly</h3>
<p>I’m not going to insult your intelligence; it’s actually really simple. Unpack the board and enclosure, and stand clear of static (ground yourself) or you’ll damage your new investment. If you have any MiniPCI cards or a CompactFlash card, install them now. Seat the board into the enclosure and use the 4  silver screws to lock it down. Use the machine screw and wing-nut to install the ground tap.</p>
<p style="text-align: center"><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_fitting.jpg"><img class="size-medium wp-image-52 alignnone" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_fitting-300x225.jpg" alt="" width="300" height="225" /> </a><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_fitting2.jpg"><img class="size-medium wp-image-53 alignnone" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_fitting2-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>Slide the cover on and use the 4 black screws to seal it up. MikroTik is also kind enough to supply rubber feet and a sticker with your router’s serial number and the MAC addresses of each Ethernet interface - place these on the bottom as you see fit. This thing is amazingly small:</p>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_assembled.jpg"><img class="aligncenter size-medium wp-image-54" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_assembled-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>(oops I forgot to install the ground tap before taking this shot)</p>
<h3>Power-on and Connecting</h3>
<p>Depending on where you purchase your equipment, your RouterBOARD may require you to install your own software or may include pre-installed software. With RouterBOARDs, there are two major choices: use MikroTik’s RouterOS (commercial software which you need to buy a license for), or just install Linux. My first thought: since there are CF card <a title="Download the Debian reference images for RB500 series at routerboard.com" href="http://routerboard.com/wp-content/uploads/rb500-128.img.zip" target="_blank">Debian reference images</a> available for the RB500 series and I’m a huge Debian fan, there’s no question here. But wait, remember that $224.45 we spent? Included is a Level 4 licensed version of RouterOS 2.9.x, already installed (read about the different licenses, but an L4 is quite generous). After reading about all of RouterOS’s functionality, and not really having the time to build the router from a base Linux install, I decided to give it a whirl - and I’m happy I did. Before you read on, definitely check out the <a title="RouterOS 2.9 Reference Manual at MikroTik.com" href="http://www.mikrotik.com/testdocs/ros/2.9/" target="_blank">RouterOS 2.9 Reference Manual</a> and what it’s capable of.</p>
<p>I’m going off on a tangent again… connect the power to your RouterBOARD and watch it light up. You’ll hear one beep on boot, and two beeps when it’s up. One problem: how do we connect to it?</p>
<p>The router has no default IP addresses configured. You can tap into the console with a PC and a serial cable to configure this (settings are between 9600 and 115200 bits/s depending on board model, 8 data bits, 1 stop bit, no parity, and hardware RTS/CTS flow control). You can also connect by MAC address using MikroTik’s WinBox tool (yes, you need Windows). Since I was using my MacBook Pro and was away from home, neither method was graceful, but we’ll only need to do this once to get IP running so I ran WinBox in Parallels (WinBox runs under Wine for linux users). While I prefer the command line, I’ll admit WinBox is a decent tool. Connect one of your router’s Ethernet ports directly to your computer (I chose the one marked Eth2) and make sure the link lights come on. You can use a straight-thru cable or a cross-over since the ports are auto-sensing. You can also connect it to your existing network but it might cause problems when configuring DHCP, etc. From this point forward, I will assume you are connecting directly to your computer to avoid any issues.</p>
<p>Download <a title="Download WinBox from mikrotik.com" href="http://www.mikrotik.com/download/winbox.exe" target="_blank">WinBox</a> and run it. Click the “…” next to the “Connect To” field, and if you’ve got everything hooked up properly, you should see your router listed here. Use “admin” for the username, and a blank password and hit “Connect”. Upon first connect, WinBox will download some plug-ins from the router to customize the functionality based on your RouterOS version and the packages that are enabled. Welcome to the pilot’s cockpit…</p>
<h3>Basic Configuration</h3>
<p>I’ll try not to bore those with reasonable networking experience by getting into basic networking principles or Security 101, but I’m also trying to give the less experienced folks a cookbook for configuring a RouterBOARD to function as an off-the-shelf router/gateway to provide access the Internet, DHCP, decent security, and a foundation for learning.</p>
<h4>Interface and IP Configuration</h4>
<p>Click “Interfaces” to view the on-board Ethernet ports. Let’s rename them to something more informative than the default names. For my configuration, I’ll be using one port (the PoE-enabled one, labeled Eth1 on the router’s enclosure, and ether1 in the software) to connect to my broadband modem, and I’ll use Eth2/ether2 to connect to my home network through a switch. Since I won’t use Eth3/ether3 right now, let’s disable it by clicking on it and clicking the “x” icon - it should turn gray. Double-click ether1 and change it’s name to wan0 so we know this connects to the Internet (or WAN), and change ether2’s name to lan0 since it connects to the local, internal network (or LAN). When you change ether2, you’ll be disconnected since the router temporarily takes the port offline for the changes to take effect - just re-connect and you’re good to go. Your configuration may look something like this:</p>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_winbox_interfaces.jpg"><img class="aligncenter size-medium wp-image-56" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_winbox_interfaces-300x177.jpg" alt="" width="300" height="177" /></a></p>
<p>Now let’s set up IP. We need to (1) give the router a static, internal IP address for devices on the local network to be able to reach it, and (2) tell the external, WAN interface to use DHCP and get an IP address from our ISP. Click the “IP” menu, and go to “Addresses”. Click the “+” icon to give lan0 a non-routable, internal address. By convention, it’s often the first or one of the first addresses in the range (I’m using 192.168.1.1), and you’ll enter your network, broadcast, and specify which interface we’re assigning to (lan0, right?). Here’s my configuration:</p>
<ul>
<li>Address: 192.168.1.1/24</li>
<li>Network: 192.168.1.0</li>
<li>Broadcast: 192.168.1.255</li>
<li>Interface: lan0</li>
</ul>
<p>Your RouterBOARD is now communicating on your LAN using the IP address you’ve just assigned to it. Before we disconnect to test it, we need to realize that in order to communicate with the router via IP, our own computer needs an IP address on the same subnet. We can either (1) configure one statically by assigning our computer something like 192.168.1.2, on a subnet of 255.255.255.0, or (2) configure our router as a DHCP server, which will hand out the appropriate IP addresses to computers on the network. For ease of administration and simplicity, let’s choose option #2 - plus it will give us some experience with DHCP. Make sure the computer you’re working on does not have a static IP address assigned, and is configured to use DHCP.</p>
<h4>DHCP</h4>
<p>Setting up a DHCP server is a three-step process: (1) setting up a pool of addresses, (2) establishing the DHCP “network”, and (3) configuring the DHCP server itself.</p>
<p>Step 1: create the pool by going to IP &gt; Pool. Click the “+” to add a new pool. I did something like:</p>
<ul>
<li>Name: lan0_dhcppool</li>
<li>Addresses: 192.168.1.100-192.168.1.199</li>
</ul>
<p>For home use, I like to keep this “segment” of the class for guest machines or devices that will be connecting and disconnecting frequently, without any specific needs beyond Internet access. Similarly, I reserve 192.168.1.1-192.168.1.10 for static leases for servers, and .11-.99 for stationary desktop static leases. You can come up with your own conventions.</p>
<p>Step 2: create the network by navigating to IP &gt; DHCP Server. Click the “Networks” tab, and click the (yes, you guessed it) “+” to add a new network. We’ll be using DHCP on our entire network, so add something like:</p>
<ul>
<li>Address: 192.168.1.0/24</li>
<li>Gateway: 192.168.1.1</li>
</ul>
<p>The gateway is important because this instructs the DHCP server to tell clients: “use the router’s IP as your gateway”. We aren’t specifying hard values for DNS because these will be automatically obtained from our ISP. These two components are all we need to get the local LAN connected to the Internet.</p>
<p>Step 3: set up the DHCP server. Still in the “DHCP Server” screen, click the DHCP tab and add a server:</p>
<ul>
<li>Name: lan0_dhcpserver</li>
<li>Interface: lan0</li>
<li>Lease Time: 3d 00:00:00</li>
<li>Address Pool: lan0_dhcppool (we created this, remember?)</li>
</ul>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_winbox_dhcp.jpg"><img class="aligncenter size-medium wp-image-55" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_winbox_dhcp-300x177.jpg" alt="" width="300" height="177" /></a></p>
<p>Congrats, disconnect WinBox by closing it, and then relaunch it. Assuming you’re handy with your operating system’s TCP/IP stack, make sure you’ve gotten an IP address assigned by the router (ipconfig on Windows, ifconfig on Linux…) Rather than connecting by MAC address, enter your router’s IP address (like 192.168.1.1) and click connect. It’s working, right?  Let’s get on the Internet.</p>
<h4>Internet and NAT</h4>
<p>Assuming you have a dynamically assigned IP address from your ISP, let’s tell the router to use DHCP to obtain it. Click “IP”, then “DHCP Client”. Add a client on the wan0 interface (you may need to fill in hostname and/or Client ID depending on your provider).  Click “Renew”. If you glance back at the “DHCP Client” window, the “IP Address” field should populate with a valid Internet IP address given to you by your provider. If not, one thing to check is if your provider requires you to register your MAC address with them to get an address. If you swapped out your old router for a RouterBOARD, you’ll need to give them a call and read off your wan0 MAC address so they can provision it.</p>
<p>So we have wan0 with an Internet IP, and lan0 with a local IP - still no Internet. We need <a title="Learn about Network Address Translation on Wikipedia" href="http://en.wikipedia.org/wiki/Network_address_translation" target="_blank">NAT</a>. Network Address Translation (or NAT) basically does the underlying translation between your local and meaningless IP addresses and the wide-open Internet. When internal devices make outbound connections, NAT slaps your wan0 IP address on those packets, and packets destined into your LAN are magically routed appropriately. Go to IP &gt; Firewall. Add a new NAT rule (these screens are getting more complicated now). Configure it something like this:</p>
<p>In the “General” tab:</p>
<ul>
<li>Chain: srcnat</li>
<li>Out. Interface: wan0</li>
</ul>
<p>In the “Action” tab:</p>
<ul>
<li>Action: masquerade</li>
</ul>
<p>So now all of your client machines which have been assigned an address via DHCP from the router can now directly access the Internet.</p>
<h4>Security</h4>
<p>Yes, your router is connected to the Internet and relatively insecure. I suppose I should have made this one of the first steps, before connecting to the Internet but we’re living on the edge here. Here are some tips for hardening your router against those malicious, crafty cyberthugs:</p>
<ol>
<li>Configure a firewall! The RouterOS firewall is based on ipchains, now <a title="Learn about iptables on Wikipedia" href="http://en.wikipedia.org/wiki/Iptables" target="_blank">iptables</a> (read up if you aren’t familiar with this logic). There are many examples out there, both simple and fairly complex ones. Google around… if I have time, I’ll post one. A best practice to keep in mind is: allow and conservatively configure what you need, and drop the rest.</li>
<li>Disable unused services. Click “IP”, then “Services”. Disable what you aren’t using. I only have ssh enabled for remote administration. Chances are you want to disable everything else. Furthermore, you can restrict ssh to only accept connections on your local network if you aren’t connecting remotely. Also, not in this list are the Bandwidth Test Server, or BTest (which keeps web port 2000 open), the MAC WinBox server, and MAC Ping Server. These are located in the “Tools” menu; make sure you disable BTest and lock down the MAC WinBox server as needed. You can also run a port-scan on your router to see what’s open using a tool like <a title="Visit the nmap homepage" href="http://insecure.org/nmap/" target="_blank">nmap</a>.</li>
<li>Disable unused packages (this doubles as a resource optimization as well). Go to System &gt; Packages and disable what you aren’t using. I’m currently using:
<ul>
<li>advanced-tools</li>
<li>dhcp</li>
<li>ntp</li>
<li>routerboard</li>
<li>routing</li>
<li>security</li>
<li>system</li>
<li>user-manager</li>
</ul>
</li>
<li>Change the default password, and better yet, disable the admin user and add your own. Click “Users” and configure to your liking. Note you can specify which address range a particular user can connect from. Speaking of passwords, there’s also a “Password” menu option in the main WinBox menu. I’m not exactly sure what this does… maybe it’s used when connecting to the console via serial. In any case, change this too.</li>
<li>Take other precautions that I probably forgot to include in this list.</li>
</ol>
<h3>Conclusion</h3>
<p>And here it is, built, configured, and in use…</p>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_inuse.jpg"><img class="aligncenter size-medium wp-image-57" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_inuse-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>The RouterBOARD 532A has been as solid as a rock since I purchased it, with the exception of a few power failures - I’ve been meaning to plug it into the <a title="Learn about Uninterruptable Power Supplies (UPS) at Wikipedia" href="http://en.wikipedia.org/wiki/Uninterruptible_power_supply" target="_blank">UPS</a>. It’s important to check log files routinely to make sure things are functioning properly and there are no security issues. It’s also important to periodically check for new versions of RouterOS and update your router when necessary. The upgrade process is a breeze: (1) enable FTP server if it is not already enabled, (2) upload new packages to the root directory, (3) reboot. RouterOS 2.9 is packed with tons of features and this post barely scrapes the surface of the device’s capabilities. At the time of writing, RouterOS 3.0 rc3 is available as well which adds even more functionality. I also did not touch on command line configuration via the terminal. You can access this with a serial cable, via telnet or ssh, or right within WinBox. The command line interface may seen a bit odd at first, but it soon becomes your best friend. For example, here’s how you might list your router’s interfaces via the command line, connected remotely via ssh:</p>
<p><a href="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_terminal.jpg"><img class="aligncenter size-medium wp-image-58" src="http://jamescoletti.com/wp-content/uploads/2008/12/routerboard_terminal-300x198.jpg" alt="" width="300" height="198" /></a></p>
<p>My only complaint thus far is the lack of RSA key support for ssh (only DSA keys are supported). Development of RouterOS and other MikroTik software is quite active. Check out <a title="The Dude network monitoring application at mikrotik.com" href="http://www.mikrotik.com/thedude.php" target="_blank">The Dude</a>, a network monitoring tool which scans subnets for devices, draws and maps network topology, and can send event-based alerts as needed.</p>
<p>Give me your thoughts, let me know what’s missing, and tell me if I screwed something up.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamescoletti.com/routerboard-rb532-assembly-and-configuration-tutorial/feed</wfw:commentRss>
		</item>
		<item>
		<title>Insert CSV file into MySQL with PHP</title>
		<link>http://jamescoletti.com/insert-csv-file-into-mysql-with-php</link>
		<comments>http://jamescoletti.com/insert-csv-file-into-mysql-with-php#comments</comments>
		<pubDate>Tue, 09 Dec 2008 23:46:19 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[csv]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[import]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://jamescoletti.com/?p=4</guid>
		<description><![CDATA[A friend needed a quick solution to this. Here's a brief explanation and a quick and dirty script for anyone that may be searching for something similar.]]></description>
			<content:encoded><![CDATA[<p>Assume you have the following file, in comma-separated value format:</p>
<p><strong>names.csv</strong></p>
<pre>1,James,admin,active
2,Jake,user,active
3,Paul,user,active
4,Suzie,moderator,active
5,Brenda,user,inactive</pre>
<p>We need to import this data into a MySQL table, and we&#8217;ll assume we have a structure that supports the data. For simplicity, something like:</p>
<pre class="syntax-highlight:sql">
CREATE TABLE users (
id INT(4) NOT NULL,
name VARCHAR(25) NOT NULL,
type VARCHAR(25) NOT NULL,
mode VARCHAR(25) NOT NULL
);
</pre>
<p>We&#8217;ll also assume we have the MySQL server running on localhost, and an account with username &#8216;test&#8217;, password &#8216;1234&#8242;, with access to database &#8216;mydb&#8217;. Here&#8217;s a quick and dirty import script.</p>
<p><strong>import.php</strong></p>
<pre class="syntax-highlight:php">
&lt;?php
/* Import CSV file into MySQL
*
* DISCLAIMER
* This is *sample* code.
* Input data is not sanitized.
* Code may not necessarily be optimized for maximum performance.
* Do not use this code in production!
*/

// ------------------------
$db_host = &#039;localhost&#039;;
$db_user = &#039;test&#039;;
$db_pass = &#039;1234&#039;;
$db_name = &#039;test&#039;;

$table = &#039;users&#039;;
// ------------------------

if ( ! $db = mysql_connect($db_host, $db_user, $db_pass)) die(&#039;Could not connect to database: &#039;.mysql_error());
if ( ! mysql_select_db($db_name, $db)) die(&#039;Could not select database: &#039;.mysql_error());

// get the table&#039;s columns
if ( ! $desc = mysql_query(&#039;DESCRIBE &#039;.$table)) die (&#039;Could not get columns from table: &#039;.mysql_error());

$fields = array();
while($col = mysql_fetch_array($desc))
$fields[] = $col[&#039;Field&#039;];

$fields_string = implode(&#039;, &#039;, $fields);
$fields_count = count($fields);

// read and parse lines from CSV file
if ( ! $file = file(&#039;names.csv&#039;, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)) die (&#039;Could not open input file&#039;);

foreach($file as $line)
{
   $line_values = explode(&#039;,&#039;, $line);

   // build SQL statement
   $sql = &#039;INSERT INTO &#039;.$table.&#039; (&#039;.$fields_string.&#039;) VALUES (&#039;;

   $values = &#039;&#039;;
   for ($i = 0; $i &lt; $fields_count; $i++)
   {
      if (is_numeric($line_values[$i]))
         $values .= (($values == &#039;&#039;) ? $line_values[$i] : &#039;, &#039;.$line_values[$i]);
      else
         $values .= (($values == &#039;&#039;) ? &quot;&#039;&quot;.$line_values[$i].&quot;&#039;&quot; : &quot;, &#039;&quot;.$line_values[$i].&quot;&#039;&quot;);
   }

   $sql .= $values;
   $sql .= &#039;)&#039;;

   // do the insert
   mysql_query($sql) or die(mysql_error());
   echo $sql.&quot;\n&quot;;
}

mysql_close($db);
</pre>
<p>The script will connect to the database and fetch all of the column names from the table. It will then open and parse the CSV file and insert, in order, each line in the CSV file as a row in the table. If a line in the CSV file contains more fields than the table, they will be ignored.</p>
<p>Place the script in the same directory as the CSV file and execute it. (PHP 5+ only)</p>
<pre>shell&gt; php import.php</pre>
<p><strong>Note: This is one solution to the problem using PHP. You can just as easily import data from any text file directly from the MySQL command line:</strong></p>
<pre class="syntax-highlight:sql">
LOAD DATA LOCAL INFILE &#039;/names.csv&#039;
INTO TABLE users
FIELDS TERMINATED BY &#039;,&#039;
LINES TERMINATED BY &#039;\n&#039;
(id, name, type, mode);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jamescoletti.com/insert-csv-file-into-mysql-with-php/feed</wfw:commentRss>
		</item>
		<item>
		<title>New site launched.</title>
		<link>http://jamescoletti.com/new-site-launched</link>
		<comments>http://jamescoletti.com/new-site-launched#comments</comments>
		<pubDate>Mon, 24 Nov 2008 15:27:32 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://jamescoletti.com/?p=4</guid>
		<description><![CDATA[I bring you a new, minimalistic version of the site, and hopefully some quality posts in the near future.
]]></description>
			<content:encoded><![CDATA[<p>I bring you a new, minimalistic version of the site, and hopefully some quality posts in the near future.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamescoletti.com/new-site-launched/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.195 seconds -->
<!-- Cached page generated by WP-Super-Cache on 2009-01-05 21:33:52 -->
