Windows Phone 7 and Zimbra September 28, 2011 2 Comments
I’ve been testing Windows Phone 7. Specifically, its compatibility with Zimbra. I am very impressed. I have to admit that I am an entrenched critic of Microsoft, and was recently reminded by a colleague why this is: http://en.wikipedia.org/wiki/Embrace,_extend_and_extinguish. Regardless of this, M$ has done a great job in implementing a mobile platform that works almost flawlessly with Zimbra and implements a standards-compliant version of ActiveSync. Given that ActiveSync is a Microsoft product, and that their phone talks this protocol talks flawlessly with any ActiveSync service, should not be a surprise to me, but it is a wonderful feat of engineering that few beyond Microsoft have been able to perfect.
I have to say that I am strangely drawn toward the platform in its simplicity and basic function. I miss the days of the non-graphical Blackberry OS with the text-based email and calendaring functions. The Windows 7 platform reminds me of this basic and flawless function. Android and iPhone seem to be riddled with a buggy glitz that is absent in the nearly perfectly executed Windows Phone 7 OS. Also impressive is that the OS provides great integration with services such as Facebook, and provides great mash-ups with your contacts too.
What I can’t deal with is the lack of popular apps. I am a hopelessly involved in the “app” culture of the iPhone and Android markets, and can’t give that up. However, if you’re a person who only cares about their contacts and email, and primarily use an ActiveSync server such as Exchange or Zimbra, I couldn’t recommend a better OS than Windows Phone 7. Hopefully, we don’t see the “extinguish” phase come too soon =).
Zimbra Backup Replication with RSYNC June 27, 2010 1 Comment
An Overview of Zimbra Backups
Creating a viable replica of a Zimbra backup can be a challenging task and the key to doing it right is to understand how Zimbra backups are structured and scheduled. The RSYNC tool is an excellent choice for an offsite replica of your Zimbra mailstore backup, as it provides options to deal with the structure. The first thing to consider is how you are backing up Zimbra in the first place. Here is a typical crontab entry detailing when and how zmbackup is called.
0 1 * * 1 /opt/zimbra/bin/zmbackup -f -a all 0 1 * * 0,2-6 /opt/zimbra/bin/zmbackup -i 0 0 * * * /opt/zimbra/bin/zmbackup -del 3m
Translated to English, this states that Zimbra is going to:
- Line1: Do a full backup of all accounts at 1:00am on Monday
- Line2: Do an incremental backup Sun, Tues, Weds, Thurs, Fri and Sat
- Line3: Get rid of any backups that are older than 3 months, and check for this every day at midnight
Now, when Zimbra does its backup job, by default it puts the backup files in /opt/zimbra/backup. If you look in this directory, you will see something similar to this:
drwxr-xr-x 5 zimbra zimbra 4096 Jun 27 01:24 . drwxr-xr-x 54 root root 4096 Mar 28 02:23 .. -rw-r----- 1 zimbra zimbra 1750611 Jun 27 01:24 accounts.xml drwx------ 2 root root 16384 Apr 26 2009 lost+found drwxr-x--- 148 zimbra zimbra 12288 Jun 27 01:24 sessions drwxr-x--- 13 zimbra zimbra 4096 Jun 27 01:24 tmp
The accounts.xml file contains vital information about the backups. Zimbra requires this information in the case of a restore and without this file, your backup will be useless. The information in this file includes:
- The translation between the Zimbra UUID for a person and their account name
- Where to look for the most recent full backup of an account
In your sessions directory, you should see the actual backup directories:
drwxr-x--- 5 zimbra zimbra 4096 Jun 24 01:23 full-20100624.052333.282 drwxr-x--- 5 zimbra zimbra 4096 Jun 25 01:20 full-20100625.052028.170 drwxr-x--- 5 zimbra zimbra 4096 Jun 26 01:30 full-20100626.053024.490 drwxr-x--- 5 zimbra zimbra 4096 Jun 27 01:24 full-20100627.052414.328 drwxr-x--- 5 zimbra zimbra 4096 Mar 27 02:05 incr-20100327.050647.501 drwxr-x--- 5 zimbra zimbra 4096 Mar 31 01:25 incr-20100331.050704.213 drwxr-x--- 5 zimbra zimbra 4096 Apr 1 01:21 incr-20100401.050711.294 drwxr-x--- 5 zimbra zimbra 4096 Apr 2 01:27 incr-20100402.050621.529 ...
Zimbra automatically uses hard links to reference message files between backup sets that have not changed since the last backup. By only storing a message for a user once, this keeps the total size of your /opt/zimbra/backup/ directory to a minimum. However, you must consider these hard links when designing your backup solution. Otherwise, you can easily make this mistake:
- If you blindly copy this data to another directory without considering the hard links, it will balloon in size at the target location, because the hard links between full backups will not be preserved and each full backup will be the full size of your mailstore. These backups should still be viable, but it would be a huge waste of space.
If you want true point-in-time recovery, you need to copy everything in /opt/zimbra/backup/ while preserving hard links. You should not pick and choose what to copy.
If you were hard-up to do something quick, a minimum emergency backup of Zimbra would include only taking the most recent full backup directory in /opt/zimbra/backup/sessions/, while preserving the /opt/zimbra/backup/ directory structure otherwise, along with the necessary accounts.xml file. However, this is not recommended. Zimbra intends for everything in /opt/zimbra/backup/ to be replicated and managed as a whole, and if you start picking it apart, you definitely will not have point-in-time recovery, and you run the risk of not getting everything that Zimbra needs to do a full restore. If you choose to pick apart the Zimbra backup scheme, make sure you understand entirely how it all works first. Also, if you use auto-group mode and if you replicate only the most recent full backup from a list of many available, a incomplete replica is all but guaranteed.
Replication with RSYNC
Zimbra stores individual messages in individual files. For small Zimbra installations, this is not a large management problem. For very large zimbra installs, this can be challenging to work with. In fact, it’s almost impossible to do this with any version of RSYNC before version 3. For more about this, see the post I did a few years ago. Since then, RSYNC has introduced a life-saving feature (“–recursive”). This is only available in RSYNC v3 and allows RSYNC to recursively traverse directories and start the initial transfer from sources with millions of files very quickly. Depending on the size of your backups, and with RSYNC v2, it could take days to even start transferring files from a Zimbra backup directory.
So, there are 2 important switches that you need to pass your RSYNC v3 process to create a fast, viable backup are:
- –recursive This takes advantage of the recursive logic in RSYNC v3
- -H This will preserve hard links, and keep the size of your /opt/zimbra/backup/ replica under control
And here it is put into an RSYNC command:
rsync -avzH --exclude="lost+found" --recursive --delete -e ssh zimbra@zimbra.server.com:/opt/zimbra/backup /my/local/replica/ > /my/local/replica.log
This assumes that you have an SSH key pair setup. Remember that RSYNC simply copies data from the source to the target. If you mistakingly delete your /opt/zimbra/backup/sessions/ directory or make some other horrible mistake, it will replicate that mistake. It is good practice to turn off your RSYNC replication before making any major changes as this replicate may be your only safeguard.
Now, about scheduling.. Run your rsync task after Zimbra typically completes its full backup and incremental backups, and leave enough time to ensure that the RSYNC completes before starting the next Zimbra backup. Depending on the size of your mailstore, this may mean staggering your Zimbra and RSYNC replica operations to each occur every other day.
Good luck with your Zimbra backup replication!
How To: 330 Gallon Rain Barrel June 6, 2010 5 Comments
Here is some information about my two 330 rain barrels. This might help you if you are interested in saving some money on your water bill and keeping a fair amount of the rainfall over your property off the watershed and from becoming just wasted runoff.

A lot of sites out there sell those 50 gallon drums for rain collections. I don’t recommend them. Regardless of the size house you have, you will easily overflow one of those things with a sprinkle of rain. I’ve even found this 330 gallon barrel to be too small, so I have installed 2, one in the front of the house and one in the back for a total of 660 gallons of rain collection.
Adding some fair size rain barrels/containers to your property is surprisingly easy and cheap. The first thing you need to do is to buy a few of the rain barrels off eBay. Search for liquid tote or tote container or the like. These containers are normally used for shipping large amounts of oils/liquids on trucks/trains. Many sellers will let you pay a little extra to have them cleaned out. Otherwise, just do your best with a hose and everything will be ok.
You can expect to pay between $70 and $120 a piece on eBay if you look around. You’re going to pay a premium for shipping as they will be delivered via truck, but that’s just the way it is.
First, find a place near your existing downspout and drain to place the barrel. Then, setup and level a pad of cinder blocks on the soil around where you want to lay the tote. Make sure that the soil is compact and level. Then, place the tote on top of the cinder blocks when it arrives.
Next, you are going to need to intercept your regular downspout with some PVC. This will likely involve getting some PVC elbows and some lengths of 4″ and 2″ pipe. Here is how I connected mine.
I simply put an elbow on the top part to angle some 4″ PVC toward the tote, then, on the overflow return, jammed some 2″ PVC down the existing aluminum hookup to the gutter drain.
The most complicated part is setting up the connector on the top of the tote so that when you get a big downpour that overflows tote, extra water will flow back into your sewer system. I’m not going to bore you with a 1000 words about this, as a picture is worth more than 1000 words. So here it is.
The key here is to cut a hole in the plastic cap that comes with your tote and glue/attach a 4″ PVC connector to it. Then, get one of the screw-in 2″ PVC connectors, drill out a 2″ hole in the side and connect the 2″ PVC in the side of the 4″ PVC. Then, get some aluminum flashing, adjustable strap some window screen and attach as shown. When the water overflows, it goes down the 2″ pipe to the sewer.
Some notes to remember about the whole thing.. First, the barrel will weigh more than 1 ton, or about 2700 pounds when full. If you don’t compact your soil before placing the cinder blocks, the barrel will list to one side or the other when weighed down. Next, don’t seal all of your PVC joints until the very end. You can probably even get away not sealing them at all. Also, you will likely need a few connectors from your hardware stores to connect the large pipe at the base of the tote to your garden hose. Use plenty of caulk/silicon on the joints.
Well, that’s it, and good luck!
Android SDK – $25 and an hour later January 1, 2010 1 Comment

If you’ve ever had an inkling to get into mobile software development, now is your time. Google has drastically narrowed the gap for wanna-be mobile developers to get into this arena with their opensource and free Android SDK (Software Development Kit). Exciting new phones such as the, HTC “Google Phone”, Motorola Droid, Motorola Cliq and MyTouch are making a splash and diverting attention away from the all-consuming iPhone market.
Android does have a bit of an identity crisis going on, no doubt because of the openness of the platform and the freedom it provides to developers hoping to capitalize on it. The marketing buzz surrounding different phones and software like Droid, MyTouch, G1, Google Phone, MOTOBLUR, Android, etc. seem to have a lot of people disoriented and on the surface, it is a bit confusing. All of these products are really only variously branded versions of a base Android OS running on a phone with some custom apps pre-installed. Android apps that you write will generally work on all of these. Here’s a breakdown:
| Common Name | Platform | OS |
|---|---|---|
| Verizon Droid | Motorola phone with some custom apps | Android 2.0/2.1 |
| Google Phone | HTC Hero phone with some Google apps | Android 2.0/2.1 |
| T-Mobile MyTouch 3G | HTC phone with some Google apps | Android 1.5/1.6 |
| T-Mobile Cliq | Motorola M200 with some Motorola “MOTOBLUR” apps | Android 1.5/1.6 |
Motorola has written “MOTOBLUR” as an application layer for Android 1.5/1.6 on the Cliq that allows corporate Exchange sync and other stuff that lets you consolidate your different accounts from Facebook, etc. Droid is a more generic version of Android 2.0 which has Exchange syncing built-in along with built-in apps for integration to Google services. It seems likely that Motorola will upgrade “MOTOBLUR” to be Android 2.0 and sideline MOTOBLUR in the future as there is a bit of overlap between what Android 2.0 and MOTOBLUR try to accomplish.

The Android SDK is available for free to download and so is Eclipse and Java. The Android OS is based on a Linux kernel and the Android GUI and API are written in Java. You can get the development environment running under MacOS X, Windows and Linux and the included documentation is excellent. Java is what enables the Android application packages (.apk files) to be installed on any architecture phone. A comprehensive development environment built on top of Eclipse allows you to visually draw the layout for your Android app, then fill in the blanks with a mix of more Java and XML. A variety of libraries built into the Android API such as Apache HTTP libs make interacting with web-based services over cell networks very easy. Also unlike Apple, a complete “service” infrastructure allows you to write daemons/services that run in the background with ease. Android incorporates the lightweight opensource database system SQLite to deal with local data storage and includes a basic library much like a registry for storing application preferences and restoring previous states of apps.
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText("sun3.org says hello!"); setContentView(tv); // Start my custom service, if it is not running already startService(new Intent(this, AndroidConnectService.class)); }
Within the SDK, you first need to become familiar with the terminology. For example, the GUI that you write is called an “Activity”, “Intents” are actions along with data (calls to activities/services) and the presentation/screen is a “Layout”, etc. Once you get familiar with the basic terminology of the Android SDK and poke around a little, a design philosophy in Android emerges regarding the sharing of access to your interfaces and services. The entire platform is designed to be very modular and to allow other developers to use your Activities and Services.

You don’t even need an Android phone to start your development, as the SDK comes with a complete emulator that lets you test your apps without the pain of installing your software on actual Android hardware every time you make a change. Incidentally, this is also a great way to test-drive Android without buying a phone or borrowing your friend’s phone.
Once you are ready to test out your app on a real phone, you’ll find that the Android OS allows you to download and install your .apk file directly from a web URL. Unlike Apple, the philosophy around Android app development is one of un-restricted access. Apple has a more restrictive App Store, and hackers need to “jail break” their phones before they can install non Apple-approved apps. Apple is only making it harder to jail break their phones. Presumably, Apple is trying to save people from themselves and their own distaste. Google has a different philosophy for Android, whereby they make the SDK components, the OS and source for the whole platform freely available and open to tinkering. It’s surprisingly easy to get an app working, tested and installed on your off-the-shelf Android phone. I had their included “helloworld” example running within about an hour, including downloading the SDK/Java JRE, poking around, compiling, testing on their emulator and installing on my regular phone.
So now you’re wondering where the $25 dollars comes in? The Android Marketplace asks $25 for you to become an official developer. This includes the ability to both upload and sell applications in the official Android Marketplace, which is akin to the Apple AppStore. Unlike Apple, there is little to no review (read “censoring”) of the apps that you sell at the Google Android Marketplace. The $25 is just to keep the spammers away. So, what are you waiting for? =)
praux.com API October 28, 2009 1 Comment

If you havn’t seen praux.com‘s fancy API, you should definitely have a look. Here’s an interface I put together that uses the API to display praux-hosted resumes on your own site. Praux is a new site that allows you to assemble, maintain and share your resume with others. The REST design and personal URLs at Praux allow you to reference, export and display your resume in many different ways. Here’s some code that uses the YAML feed of your praux.com resume, to render it on your own site. You will need the spyc YAML parser to use the below script. Have fun!
<? require_once("spyc.php"); $data = file_get_contents("http://your.url.praux.com/yaml/"); $resume = spyc_load_file($data); echo "<b>" . $resume[name] . "</b><br>"; echo "<b>" . $resume[email] . "</b><br>"; echo "<b>" . $resume[phone] . "</b><br><br>"; $sections = $resume[sections]; function recurse_child($child,$level=0,$lastout=false,$subsection=0) { $level++; if ($lastout==false) { $level--; } if (is_array($child)) { foreach ($child as $itemid => $item) { if (is_array($item[content_items])) { if ($item[content_items][0][body]) { echo "<span style='display:inline;position:relative;left:120px;'>"; echo str_repeat(" ",$level*8); echo "</span>"; echo "<div style='display:inline;position:relative;left:135px;'>"; echo "<span style='position:absolute;left:-15px;font-size:1.0em;'>"; echo "•"; echo "</span>"; echo trim($item[content_items][0][body]); echo "</div>"; echo "<br>\n"; $lastout=true; } if ($item[content_items][0][date_range]) { if ($subsection > 0) { echo "<br>"; } $subsection++; echo $item[content_items][0][date_range] . " "; echo "<span style='position:absolute;left:120px;'>"; if ($item[content_items][0][organization]) { echo "<b><i>" . $item[content_items][0][organization] . "</i></b>, "; } else { echo "<b><i>" . $item[content_items][0][title] . "</i></b>, "; } echo $item[content_items][0][locality]; echo "</span><br>"; echo "<span style='position:absolute;left:120px;'>"; echo $item[content_items][0][title]; echo "</span><br>"; } if (is_array($item[children])) { recurse_child($item[children],$level,$lastout,$subsection); } } } } } echo "<div style='position:absolute;width:600px;'>"; foreach ($resume[sections] as $sectionid => $section) { foreach ($section[content_blocks] as $blockid => $block) { echo "<span style='font-size:1.5em;'>" . $block[content_items][0][body] . "</span>"; echo "<span style='position:relative;'><hr></span><br>\n"; foreach ($block as $childid => $child) { recurse_child($child); } echo "<br>"; } } echo "</div>"; ?>
Ubuntu (Dapper) on the PC Engines Alix 3D1 October 25, 2009 11 Comments

The Alix 3D1 is a small PC with an LX700 AMD Geode cpu. It costs $75 USD and can, with enough patience, run just about any mainstream Linux OS that you can think of. That is thanks to the AMD Geode processor, which is i386/x86 compatible, so you won’t need any special ARM distributions or the like to get the thing going.
This is a tutorial on installing specifically the Ubuntu Dapper distro on the Alix 3D1 with the help of a Windows PC.
For some reason mainstream Ubuntu installs after Dapper have issues completing the installation procedure and will likely cause problem for you. If you are able to install something released after Dapper, please let me know!
Where to buy an Alix 3D1
First of all, I’ll post some info about where to get the Alix 3D1. It is made by a company called PC Engines and there are 3 different versions of the board. The cheapest is the 3D1 ($75).
This tutorial also should apply to the 3D2 model. The 3D3 model has an Award BIOS and a VGA port, so things might be a little different with that one (and likely easier). Available distributors:
What you need to get with the Alix 3D1
The 3D1 comes in a cardboard box with nothing but the motherboard and some anti-static packaging, so you’re going to need to order a few accessories with it too:
- A power supply
- An enclosure. You can’t go wrong with the metal waterproof one, it’s very nice.
- If you’re planning on doing 802.11, you’ll want the type-N coaxial pigtails for any NICs you are adding to the 3D1′s 2 miniPCI slots.
- A Compact Flash (CF) card preferably about 4GB or larger
Total cost for the Alix 3D1, power supply, waterproof closure with mounts and 2 type-N 802.11 pigtails was only $146.90 USD.
Accessing the Serial Console

First thing you will need to do is to get access to the console on the 3D1. I’m using Windows, so the best terminal program out there (AFAIK) is PuTTY. You can download PuTTY from:
After you have PuTTY installed, you will need a serial cable with a null-modem adapter. Connect the serial cable with null-modem to the 3D1 to your Windows PC and start up PuTTY. Select ‘Serial’ for connection type and put the baud rate at 38400 and type in the COM port (COM[1-X]). 38400 is the default baud rate of the 3D1.
PC Engines ALIX.3 v0.99 640 KB Base Memory 130048 KB Extended Memory 01F0 Master 848A SAMSUNG CF/ATA Phys C/H/S 992/16/32 Log C/H/S 992/16/32
Booting Ubuntu (Dapper) via PXE
The best way I’ve found to load a Linux distro on the box is to use the built-in PXE boot functionality of the BIOS. When the BIOS on the 3D1 boots, it does a DHCP broadcast to find any available PXE boot servers out there. You don’t have to worry about other DHCP servers on your network responding unless they are especially setup to do PXE. PXE uses your specialized DHCP server + TFTP (setup below) to bootstrap the device. If everything is setup correctly below, your DHCP server responds and provides an image for the device to download and run (bootstrap). After the image is downloaded and executed, then the fun begins.
This seems like a lot of stuff to get configured to do this, but luckily, there is some software that makes this pretty straight foward. The best utility I’ve found to do this a Windows program called TFTPD32:
You will first need to prepare a directory on your Windows PC for the TFTP server to serve out a kernel and a boot image. Create a directory on your windows machine for the files. I called mine C:\tftpd.
Downloading and preparing Ubuntu Dapper netboot.tar.gz
Download the following package to your C:\tftpd directory:
You will need a program to unzip .gz and extrat .tar files. A great one for Windows is 7-Zip, which is available here:
After the archive is in the directory, extract the .gz, then the .tar underneath the c:\tftpd directory. After this is done, you’re ready to prepare your TFTP and DHCP servers.
Setting up TFTPD32
You will need to setup your TFTPD32 application as follows. You are going to need to enable ‘PXE Compatibility‘ as well as make sure that DHCP and TFTPD servers are enabled. Also, be sure to set the path correctly for your ‘base directory‘ as shown, as well as setup your new DHCP server to give normal addresses on your network. The DHCP server that you setup here will serve up the correct boot image when an address is given out to the 3D1. There is an area to to input what image you want to provide to new DHCP hosts. In this textbox under the DHCP tab of TFTPD32, enter ‘pxelinux.0‘. Make sure that your default gateway, actual DNS server, subnet and IP ranges all make sense in the configuration. If you have problems getting PXE booting to work, be sure to look at your logs tabs. They are invaluable for debugging what is wrong.

Starting up the Alix 3D1!
When you first startup the 3D1, you are going to need to modify the BIOS config to allow PXE booting. To do this, type ‘S’ when the 3D1 is testing memory. This should bring up a menu of options. To toggle PXE booting, type ‘N’, then save the configuration to the BIOS.
PC Engines ALIX.3 v0.99 640 KB Base Memory 130048 KB Extended Memory 01F0 Master 848A SAMSUNG CF/ATA Phys C/H/S 992/16/32 Log C/H/S 992/16/32 BIOS setup: (9) 9600 baud (2) 19200 baud *3* 38400 baud (5) 57600 baud (1) 115200 baud *C* CHS mode (L) LBA mode (W) HDD wait (V) HDD slave (U) UDMA enable (M) MFGPT workaround (P) late PCI init *R* Serial console enable *E* PXE boot enable (X) Xmodem upload (Q) Quit Save changes Y/N ? Writing setup to flash...
When the 3D1 boots back up it, should start checking for a DHCP server, see the TFTPD services you have running, grab an available IP address from your DHCP server and start to load the kernel.
PC Engines ALIX.3 v0.99 640 KB Base Memory 130048 KB Extended Memory 01F0 Master 848A SAMSUNG CF/ATA Phys C/H/S 992/16/32 Log C/H/S 992/16/32 Intel UNDI, PXE-2.0 (build 082) Copyright (C) 1997,1998,1999 Intel Corporation VIA Rhine III Management Adapter v2.43 (2005/12/15) CLIENT MAC ADDR: 00 0D B9 13 CD 7C CLIENT IP: 192.169.0.20 MASK: 255.255.255.0 DHCP IP: 192.169.0.250 GATEWAY IP: 192.169.0.1
Monitoring the TFTPD32 Logs
You should now see some activity in the TFTPD32 logs. The following would be a good sign:
Read request for file <pxelinux.cfg/default>. Mode octet [25/10 17:20:35.078] OACK: <tsize=1821,> [25/10 17:20:35.078] Using local port 2360 [25/10 17:20:35.078] <pxelinux.cfg\default>: sent 4 blks, 1821 bytes in 0 s. 0 blk resent [25/10 17:20:35.140] Connection received from 192.169.0.20 on port 57099 [25/10 17:20:35.140] Read request for file <ubuntu-installer/i386/boot-screens/boot.txt>. Mode octet [25/10 17:20:35.140] OACK: <tsize=301,> [25/10 17:20:35.156] Using local port 2361 [25/10 17:20:35.156] Connection received from 192.169.0.20 on port 57100 [25/10 17:20:35.234] <ubuntu-installer\i386\boot-screens\boot.txt>: sent 1 blk, 301 bytes in 0 s. 0 blk resent [25/10 17:20:35.234] Read request for file <ubuntu-installer/i386/boot-screens/splash.rle>. Mode octet [25/10 17:20:35.250] OACK: <tsize=8023,> [25/10 17:20:35.250] Using local port 2362 [25/10 17:20:35.250] TIMEOUT waiting for Ack block #0 [25/10 17:20:50.343]
Ok, here’s the tricky part
Ubuntu will by default try and send the console output to a VGA source. Since there is not a VGA source on the 3D1, you are going to have to do tell it to send the console to the serial port. Problem is, you cannot see that it is currently at a boot prompt asking you what to do. In the TFTPD server logs, you should be able to see that it has grabbed the pxelinux.0 file and is waiting on something. This is your queue!. Type into PuTTY the following (you will not be able to see the output of your typing):
linux console=ttyS0,38400
..and hit Enter.

Within about 10 seconds, you should see the console outputting to your PuTTY window and the kernel booting. Your 3C1 should now have a valid IP, Netmask, router and DNS server configuration and it should continue to install Ubuntu from the Ubuntu network archives server. The rest is a piece of cake!
Credits
The following site(s) were very helpful in creating this tutorial
GroupWise 6.5 to Zimbra AddressBook August 22, 2009 No Comments
Here is some code to translate a GroupWise 6.5 address book into a format that Zimbra can understand.
nab2zimbra.php
<?php function get_value_by_mapi($zimbraid, $nabid,$nabvalues,$nabfields) { if ($nabid == "") { return ""; } for ($i=0;$i<sizeof($nabfields);$i++) { if ($nabfields[$i][mapitag] == $nabid) { return $nabvalues[$i]; } } } if (count($argv) < 2) { echo "Usage: php nab2zimbra.php <input_file.nab> \n"; } else { $inputfile = trim($argv[1]); if (file_exists($inputfile)) { $row = 1; $handle = fopen($inputfile, "r"); /* :::TAGMAP:::0FFE0003:***, 3001001E:Name, 3A08001E:Office Phone Number, 3A18001E:Department, 3A23001E:Fax Number, 3003001E:E-Mail Address, 3A06001E:First Name, 3A11001E:Last Name, 3A17001E:Title, 3A29001E:Address, 3A27001E:City, 3A28001E:State, 3A26001E:Country, 3A2A001E:ZIP Code, 3002001E:E-Mail Type, 3A19001E:Mailstop, 3A09001E:Home Phone Number, 3A1C001E:Cellular Phone Number, 3A21001E:Pager Number, 3A1A001E:Phone Number, 600B001E:Greeting, 600F001E:Owner, 3A16001E:Organization, 3004001E:Comments, 3A00001E:User ID, 6604001E:Domain, 6609001E:Additional Routing, 6605001E:Post Office, 6603001E:GUID, 6607001E:eDirectory Distinguished Name, 6608001E:Network ID, 660D001E:Internet Domain, 660E001E:AIM/IM Screen Name, 3A45001E:Prefix, 3A44001E:Middle Name, 3A05001E:Generation, 3A5D001E:Home Address, 3A59001E:Home City, 3A5C001E:Home State, 3A5B001E:Home ZIP, 3A5A001E:Home Country, 3A50001E:Personal Web Site, 3A51001E:Office Web Site, 6612001E:Resource Type, 6615001E:Primary Contact Name */ // First go through the input file and load an associative array with mapped MAPI tags $fields = array(); while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { if ($row==1) { $num = count($data); $row++; // This should be the header line $fieldmap = array(); for ($c=0; $c < $num; $c++) { $thismapitag = ""; $exploded = explode(":",$data[$c]); $thismapitag = $exploded[0]; $fieldmap[$c][value] = $exploded[1]; $fieldmap[$c][mapitag] = $thismapitag; } } else { $num = count($data); $row++; for ($c=0; $c < $num; $c++) { // Zimbra mapping /* birthday company = 3A16001E department = 3A18001E dlist email = 3003001E email2 email3 fileAs = 1,2,3 firstName = 3A06001E fullName = 3001001E homeCity = 3A59001E homeCountry = 3A5A001E homeFax = homePhone = 3A09001E homePhone2 homePostalCode = 3A5B001E homeState = 3A5C001E homeStreet = 3A5D001E homeURL = 3A50001E initials jobTitle = 3A17001E lastName = 3A11001E middleName = 3A44001E mobilePhone = 3A1C001E nickname notes = 3004001E pager = 3A21001E type workCity = 3A27001E workFax = 3A23001E workPhone = 3A08001E workPhone2 workPostalCode = 3A2A001E workState = 3A28001E workStreet = 3A29001E workURL = 3A51001E */ $fields[$row][$c] = $data[$c]; } } } fclose($handle); // Ok, now build the header row: $zimbraheader = array("birthday","company","department","dlist","email","email2","email3","fileAs","firstName", "fullName","homeCity","homeCountry","homeFax","homePhone","homePhone2","homePostalCode","homeState","homeStreet","homeURL","initials","jobTitle","lastName","middleName","mobilePhone", "nickname","notes","pager","type","workCity","workFax","workPhone","workPhone2","workPostalCode","workState","workStreet","workURL"); for ($i=0;$i<sizeof($zimbraheader);$i++) { echo $zimbraheader[$i] . ","; } echo "\n"; // Loop through all the input rows foreach ($fields as $key => $val) { $nabfields = $fieldmap; $nabvalues = $fields[$key]; // Only import people objects, not company objects. if ($nabvalues[0] == "U") { echo get_value_by_mapi("birthday", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("company", "3A16001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("department", "3A18001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("dlist", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("email", "3003001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("email2", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("email3", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("fileAs", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("firstName", "3A06001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("fullName", "3001001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homeCity", "3A59001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homeCountry", "3A5A001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homeFax", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homePhone", "3A09001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homePhone2", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homePostalCode", "3A5B001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homeState", "3A5C001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homeStreet", "3A5D001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("homeURL", "3A50001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("initials", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("jobTitle", "3A17001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("lastName", "3A11001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("middleName", "3A44001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("mobilePhone", "3A1C001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("nickname", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("notes", "3004001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("pager", "3A21001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("type", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workCity", "3A27001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workFax", "3A23001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workPhone", "3A08001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workPhone2", "",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workPostalCode", "3A2A001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workState", "3A28001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workStreet", "3A29001E",$nabvalues,$nabfields) . ","; echo get_value_by_mapi("workURL", "3A51001E",$nabvalues,$nabfields) . ","; echo "\n"; } } } else { echo "Could not find input file: " . $inputfile . " \n"; } } ?>
Favorite EBay Searches January 19, 2009 No Comments
EBay is a place that lacks description. It is a staple of the Internet, and is often criticized for being a hodge-podge outlet that resembles a dollar store. However, there are treasures that can be found on EBay that extend well beyond what can be purchased at your local store. Now, I know you can probably find lots of crazy things for sale at specialized Internet stores.. But really, where else but EBay can you find 100′s of vendors selling them in an atmosphere of free market competition? Here are a few of my favorite EBay searches and some information about them.
Ancient Roman Stuff
Ancient Roman artifacts are plentiful on Ebay. The Roman empire lasted nearly 1200 years and encompassed, at its peak, nearly 2.3 million square miles of what is now the general area known as Europe. 88 million people called Rome their capital, at the peak. The peak of the Roman civilization lasted from 27 BC – AD 476, that’s a minimum 1,533 years ago. Museums are filled with the best of Roman stuff. So much so, that they rarely accept new artifacts, unless they are exceptional. What that means for you is that you can have an incredible piece of history for almost nothing. One of the common pieces of Roman history sold on EBay are ancient roman coins. These coins come in a variety of states and conditions. They are often sold “uncleaned”, which means that the people who found them (often with a metal detector in “hordes”), have not stripped the corrosion from their surface. However, you can be quite assured that they have kept any pieces that are gold or silver.
About a year ago, I got mildly curious about these coins and ordered a set of 20 or so un-cleaned Roman coins. After following the detailed directions for cleaning that came with the coins, I found about 1/4 of them cleaned reasonably well. Here is a detail of one of these coins. I have no idea who/from where the militant looking guy or lady is on the surface, but it was a lot of fun for about $10 bucks.
A Roman coin that I cleaned

Search ‘Ancient Roman’ on Ebay
Surgical Supplies
You simply cannot find some treasures at your local retail outlets, or anywhere else for that matter. This includes stuff like surgical sutures. You or someone you know has probably been in situation where you were far away from medical help and needed it quickly. Unfortunately, many medical establishments, especially those in the US figure that you are an absolute idiot and can’t tend to your own body or that of someone else, without a 10 year degree. With a little bit of You Tube training, you can easily suture an open wound and maybe save someone from disfigurement or death from loss of blood. The only problem is that you can’t buy the basic supplies needed to tie a suture, a med school 101 procedure. At least in the US, your local pharmacy doesn’t carry this stuff. But on EBay, it’s a click away.

Search ‘suture’ on EBay
Well, that’s it for now. I’ll be sure to be back with more EBay treasures soon =)
iCAMView Pro November 27, 2008 No Comments
If you’ve ever searched on eBay or Google for IP-based camera security things, you’ve undoubtedly seen advertisements for these little plastic USB camera servers called the iCAMView. I finally got curious about these things and ordered one off eBay. I’ll admit, they’re really impressive. One of the downfalls of many IP-based cameras and camera servers is always the software. In general, you get what you pay for in this regard. However, the iCAMView device software is excellent.
The one thing that grabbed my attention about the iCAMView is that they recently released a new version of the device called the “iCAMView Pro”, which can use higher resolution USB cameras. Image resolution is one of my pet peeves and largely why I generally choose to stay away USB-based camera servers.
Once I started testing the device, a few things caught my eye. First, there is an option to automatically reboot the device at a specified interval. Most manufacturers of these things have some ridiculous idea that their devices will stay running indefinitely, without rebooting. I’ve tested many IP camera devices and they universally eventually lock up or start running slow. At least the iCAMView people were humble enough to add this option.
Secondly, you can plug a USB storage device into the thing for local storage. It even manages old files and deletes them when the storage hits a user-specified limit. This is another thing they added to the software to make the device a “set it and forget it” camera server.
Third, it’s fast! I don’t know how they manage to put a full web server packed with features such as motion detection in such as small package, but it’s amazing how responsive the web interface is, even when it’s actively capturing photographs.
Fourth, it supports many wireless USB dongles and even supports WEP encryption/keys.
Overall, the device is very impressive and well worth a look. It has user upgradable firmware and I’ll soon be testing the higher resolution USB cameras with it.
Cheap Computing: The “DecTop” August 24, 2008 No Comments
Do you remember AMD’s effort to populate the world with cheap PCs? Well, AMD ultimately stopped manufacturing their “PIC” (a.k.a the Personal Internet Communicator) machine themselves, but handed the right to sell that device to Data Evolution Corporation in late 2006 who is now selling it as the “DecTop”.

Data Evolution’s DecTop (Can be had is small quantity for $88 shipped)
The machine itself was designed to be an effort in the production of cheap computers. It is still very cheap at qty 1 ($99) and can be purchased directly from Data Evolution Corp online. In fact, they now are offering a “4 for 3″ deal, which brings the individual cost down to around $88 shipped if you can split the cost between friends. The shipping costs are outlandish, but it still ends up a good deal.
It features a 366MHz AMD geode processor and a full size 3.5″ hard drive. The ram is a single 128MB 200pin SO-DIMM which can be upgraded to 512MB. I had a need for 2 such minimalist machines. One for a simple SSH gateway and the other for an MP3 player. So I figured I’d give these things a try. The site doesn’t give very much information about them, but there are some good resources out there regarding this thing. One of the unfortunate things about them is that they don’t have USB 2.0 ports, which would have made them a great choice for a NAS device. Strangely, it comes with a USB ethernet adapter. You’d think that something originally called an “Internet Communicator” would at least have that built-in. It does however have a built-in modem =).
One of the ways they keep the cost down is to use commodity parts such as the upgradable 10GB 3.5″ IDE (old style) hard drive. These drives are probably bought for almost nothing and likely avoid the higher cost of SSDs, 200GB+ SATA HDs, 2.5″ laptop drives and other flash-based disk that tend to make their way into “cheap” computers nowadays. I think there is a fairly huge market for cheap, small embedded-style PCs (emphasizing cheap first). Unfortunately, the embedded PC/Linux market hasn’t really tapped this yet, as when everything is said and done, you usually will end up paying much more for small embedded machines than you would a full-sized desktop. The DecTop is a clear exception to this rule.
Some companies have seen good success selling more expensive “tinker” devices like Bug Labs, who sells a modular embedded system called the “Bug” for hobbyist geeks/dorks like myself. Still, the Bug is not nearly as cheap as the DecTop and sells for ~$350, just for the base system. It’s got the right spirit, just not the price to make it a cheap machine.

Bug Labs “Bug” (retails for $350+)
A better option than the Bug for a cheap machine is the Norhtec MicroClient JrSx. This machine is a slimmed down version of its brother the MicroClient Jr. It has a slightly more substantial list of features than the DecTop and comes with a CF slot and USB 2.0. However, it does not come with a hard drive . You are expected to either install a 2.5″ IDE disk or a CF card for your OS. It does optionally come with a mini-PCI slot so that you can add on nice things like wi-fi or other controllers. The CPU is an all-in-one 486SX running at 300MHz, a bit slower than the DecTop and with slower bus speed. Nohrtec advertises 128MB of on-board ram which does not appear to be expandable. Like the DecTop, shipping is completely unreasonable @ ~$53, however the base price for the machine is only $85 ($93 with mini-PCI or HD connector), bringing the cost of this base machine to ~$138-$146 shipped, a bit more than the DecTop, but still easily in the league of cheap machines.

Nohrtec MicroClient JrSX (retails for $138 shipped)
With all these efforts at cheap machines, it seems like fast, pluggable I/O and expandable RAM seem to be lacking. All this makes me wonder if there is a perfect cheap PC? It seems as though this could be accomplished by:
- 1 PC-on-a-chip
- 1 1Gb Ethernet Port
- 1 SO-DIMM slot
- 2 USB 2.0 ports
- 1 CF Slot
- 1 VGA port
This is fairly close to the Nohrtec box except for the SO-DIMM slot. In fact, a base system with no ram should be cheaper. I’d bet this could be marketed and sold at a profit for around $100 or less given what I’ve seen so far. Sure, there would plenty of people who would whine about absence of HDMI, FireWire, 802.11, etc., but what do they want for $100? I think it would score big, at least with people like me =)


