Wednesday, December 23, 2009

An excellent PHP script to handle time difference

I am working on a project that involves displaying the time difference between a start and end time on a website.

The following script is lifted directly from:

* A function for making time periods readable
* @author Aidan Lister
* @version 2.0.0
* @link
* @param int number of seconds elapsed
* @param string which time periods to display
* @param bool whether to show zero time periods
function time_duration($seconds, $use = null, $zeros = false)
// Define time periods
$periods = array (
'years' => 31556926,
'Months' => 2629743,
'weeks' => 604800,
'days' => 86400,
'hours' => 3600,
'minutes' => 60,
'seconds' => 1

// Break into periods
$seconds = (float) $seconds;
foreach ($periods as $period => $value) {
if ($use && strpos($use, $period[0]) === false) {
$count = floor($seconds / $value);
if ($count == 0 && !$zeros) {
$segments[strtolower($period)] = $count;
$seconds = $seconds % $value;

// Build the string
foreach ($segments as $key => $value) {
$segment_name = substr($key, 0, -1);
$segment = $value . ' ' . $segment_name;
if ($value != 1) {
$segment .= 's';
$array[] = $segment;

$str = implode(', ', $array);
return $str;

Tuesday, December 8, 2009

Things to do with an iPod and Fedora

My iPod Nano 8gb. ( not the fancy new one with the video ) works perfectly well inside fedora so long as you bear in mind the following basic points:
  1. The thing doesn't play ogg files so if you have any of those on your system, they can not be synced.
  2. Depending on the application you use, you end up with podcasts being saved under music.
  3. Sometimes you get images sometimes you don't.
  4. Albums with Various Artists do not appear under compilations. Instead your Artists menu shows a long list of artists most of which only have one track.
Applications that ship with fedora and support the iPod:
  1. gtk-pod ( manage your ipod )
  2. gpodder ( download podcasts etc - these actually go into the podcasts menu on the device. )
  3. Amarok
  4. Rythmbox

Other music applications I have played with that support the iPod:
  1. Songbird 2
I should not here that once again, I have found that Amarok 1.4 is still the best player out there. I had to install it using the F11 binaries ( just search for them on google ) and a couple of symlinks:
  1. ln -s /usr/lib64/
  2. ln -s /usr/lib64/
So there you go!

Wednesday, November 25, 2009

Bash Plus Spaces In Filenames Equals Headache


Check this out:

Saturday, November 21, 2009

Understanding Redhat Kickstart

Kickstart provides linux system administrators a method for installing linux on pc's in unattended mode. A properly formatted Kickstart configuration will perform all tasks such as setting the root password, the networking interfaces, the disk partitioning scheme as well as the installation of packages.

I needed to build a clustered reverse proxy the other day to test if it could be used for SSL termination. I was looking for a way to aggregate multiple webservers behind a proxy server so that they could have their SSL terminate at the proxy, then the HTTP traffic passed through a Level 7 ( application layer ) scanner to test for sql injection and the like.

So I fired up my trusty Virtualbox and built a standard Centos 5.4 server. I copied the CD into the ftp directory and started NFS with an export to that FTP directory. This server was to serve as an install NFS server for the 2 proxy servers as well as a yum repository for them. That's why I placed the CD files in the FTP location.

So here is my example proxy diagram. It is very similar to the basic version in my previous post. I needed to make sure that the proxy servers had apache installed on them for the reverse proxie's and heartbeat. I ended up manually installing heartbeat. I had my reasons... :)

The trick making a successful kickstart file is to take one that is generated for you by anaconda. Anaconda is the software that installs your new Redhat based system. After a manual install is complete a copy of the kickstart file for that installation is stored in: /root/anaconda-ks.cfg

I simply copied this over to /var/www/html/ks.cfg and began editing it with vi. Here is the result of that editing...
[root@server html]# cat ks.cfg
# Kickstart file automatically generated by anaconda.

nfs --server --dir=/var/ftp/pub/server
lang en_NZ.UTF-8
keyboard us
network --device eth0 --bootproto dhcp --nameserver
rootpw --iscrypted $1$ewn======YEAH RIGHT!==2hBDFz1
firewall --enabled --port=22:tcp
authconfig --enableshadow --enablemd5
selinux --enforcing
timezone --utc Pacific/Auckland
bootloader --location=mbr --driveorder=hda
clearpart --all
part / --fstype ext3 --size=0 --grow --ondisk=hda
This file does the following things in order:
  1. Does an INSTALL and not an UPGRADE
  2. Defines the location of the NFS share from which to install from.
  3. Sets the default language
  4. Sets the default keyboard layout
  5. Sets up the network interface
  6. Specifies the root password ( i have masked mine here )
  7. Turns on the firewall and allows port 22 for SSH through it.
  8. Configures authconfig to allow shadow passwords and md5 encryption.
  9. Turns SELINUX on and sets it to ENFORCING mode.
  10. Sets the timezone.
  11. Defines where the bootloader will be installed. Master Boot Record on the disk HDA
  12. Zeros the master boot record
  13. Clears all partitions
  14. Defines one partition mounted on / ( root ), filetype ext3, 0 min size configured to grow to extents of disk and on disk HDA
  15. Sets up packages. Package Groups are preceeded with an @ symbol, individual packages are named normally one per line and packages to exclude are preceeded with a - symbol.
There is one very useful feature left out and that is POST INSTALLATION SCRIPTS. This is a script that will be executed after the system has installed and might used for creating default users or determining which services to turn on and off after an install.

All going well the above VERY BASIC kickstart file should result in a completly automated install, assuming your NFS share is available and the machine can connect to a DHCP server and be assigned an IP address.

Try it out some time. It's quite fun to watch.

Sunday, August 2, 2009

Scheduled Tasks on HA Pairs in Windows

Sometimes you might find yourself deciding that a Scheduled task is required for some report or file transfer on a production system. The production system, however, is part of a high availability (HA) pair. The particular method of dealing with HA in this particular ( hypothetical of course ) case works by moving an IP Address called a Virtual IP address between the servers of the HA Pair. Whichever server holds the VIP is the current node.

Your application needs to know if it is executing on the current node before starting.

Wrap your application in a very simple snippet of Comand Line script that:
  1. Looks for the VIP in ipconfig.
  2. If no errors found then jump to the section of your script that launches your application or another script to do the task.
  3. If an error is found then jump to the section of your script that notifies the log.

@echo off

ipconfig /all | find %VIPTHATWORKS%

REM #We are here becuase the find returned a result.
REM #It is safe to execute the rest of the application.
echo "VIP Found. - Continuing with application..."

REM #Pause for user input.

REM #This part of the script is where you would handle any
REM #error logging or other admin related
echo "Could not find a VIP. - Exiting"

REM #Pause for user input.

echo "end of script reached."

Saturday, August 1, 2009

Things to do with an iPod

I have had my iPod 8gb Nano ( Video ) for about 4 months now and I have been having heaps of fun with it. I know it's not cool like an iPod Touch or iPhone but it is still plenty powerful.

I have tried using it with Linux and although it is supported in Amarok ( I am still on Amarok 1.4 due to lack of Fedora packages for the new version which actually has replay-gain for Xine included ) I have found that the support for pod casts is a little limited. For example: I like to download all the pod casts in a feed at once so that I can catch up to the current feed. So I stick with iTunes. This means sticking with a windows pc or if you are lucky to own one, a mac.

Initially I spent heaps of time building the perfect play list on my iTunes and moving that over to the iPod. This was fun but only for a short while. The main problem being that no matter how many weeks of music you have on your iPod, you still end up with the feeling that you have heard it all before.

I was struck by the "Only options is to rebuild windows" bug recently. You might know that as the, "My Computer is getting slower and slower and doesn't shut down properly anymore" bug. Stupidly, I had no backup of my iTunes library so I lost the whole thing. About 200 CDs worth. Nice...

What was initially looking like a bad thing for me has really turned into a blessing in disguise. A friend suggested I try an audio book and pointed me to Its a great resource for free audio books, usually read by the Author. If you sign up you can subscribe to audio books which are exposed via an XML feed which is completely compatible with iTunes. Just select how you want the feed to be released to you: once a day, once every 3 days etc. and then select the Subscribe Via iTunes button. If the book is complete, ie: All episodes are available, then you can click the release all episodes now button and then subscribe to the feed provided. All episodes will be loaded into your iTunes library ready for you to click the "Get All" button.

All in all I seriously recommend Podiobooks. I suggest you start off with, "Infected" by Scott Sigler. Its a dark / fantasy kind of book with horror content but a riveting story. I was hooked within 5 minutes and found myself looking forward to my next bus trip to work so I could find out more about Perry Dawcey's plight...

Happy listening.

Friday, July 31, 2009

Rip from WAV to MP3 and add ID3 tags -- All with Perl

Ok - so I know I have said before that I am not much of a perl fan. ( yes it's safe, I am wearing my flame proof suit. )

I will, however, say now; I am coming around. It would seem that I am starting to see the light. I needed to extract some files from a CD I have and convert them to MP3. The CD was not made with extracting to mp3 in mind if you get my drift. It's ok, because the CD is my copy and I want to listen to it on my iPod. Regular extracting on iTunes was not working out for me. So I rolled my chair over to my trusty Linux Box and perl, id3, cdparanoia and lame.

First thing I did was use cdparanoia to extract all the tracks. This went swimmingly leaving me with a folder full of files called 01.cdparanoia.wav or something just as useless. The files played ok but I needed to name them all. This particular CD was not listed on Music Brainz so I couldn't do anything fancy with FreeCDDB or whatever they call that now days.

* shudder * - I had to manually edit 17 filenames. I left the .wav extensions of course. I thought that I might need to get the tags later so I decided to choose a naming scheme for my file names.

01-My Song Title_My Artist Name.wav

and so on.

Then I wrote a little script that:
  • Loops through each file in a folder with the .wav extension
  • Saves a variable with the file name but with .mp3 instead of .wav
  • Regexes ( new word ) out the various parts of the file name into $track, $title, $artist ( thanks to the nice naming scheme this was easy. )
  • Uses Lame to convert the file. Lame now days is pretty cool.
  • Uses id3v2 to add the tags extracted from the file name. I can use amarok to add the album titles etc once it is imported into Amarok.
Here is the script:
#!/usr/bin/env perl

@files = <*.wav>;

foreach $file (@files) {

$newfile = $file;
$newfile =~ s/\.wav/\.mp3/;

$file =~ m/^(.*)-(.*)_(.*).wav/;

$track = $1;
$title = $2;
$artist = $3;

system("lame", "--preset", "cd" ,"$file" ,"$newfile");
system("id3v2", "--artist", "$artist", "$newfile");
system("id3v2", "--song", "$title", "$newfile");
system("id3v2", "--track", "$track", "$newfile");


Thursday, July 30, 2009

Real simple to connect to MSSQL from Perl

Again, this took me a little while but here I am. Connecting to a database ( SQL SERVER 2008 ) from a Windows Server 2008 VM I own ( thanks TECH ED 2008 ) and Active State Perl.

Install Scite cos it's a nice editor and you are away laughing...


use DBI;

my $DSN = 'driver={SQL Server};Server=localhost; database=AdventureWorks;TrustedConnection=Yes';
my $dbh = DBI->connect("dbi:ODBC:$DSN") or die "$DBI::errstr\n";

my $sth = $dbh->prepare('select top 10 * from Sales.vSalesPerson')
or die "Couldn't prepare statement: " . $dbh->errstr;


while( @data = $sth->fetchrow_array())
foreach(@data) {
print "[$_]";
print "\n\n";



[268][][Stephen][Y][Jiang][][North American Sales Manager][238-555-0197][stephen][0][2427 Notre Dame Ave.][][Redmond][Washington][98052][Un
ited States][][][][677558.4653][.0000]

[275][][Michael][G][Blythe][][Sales Representative][257-555-0154][michael9@adven][1][8154 Via Mexico][][Detroit][Michigan][48226][United States][N
ortheast][North America][300000.0000][4557045.0459][1750406.4785]

[276][][Linda][C][Mitchell][][Sales Representative][883-555-0116][linda3@adventu][0][2487 Riverside Drive][][Nevada][Utah][84407][United States][Sou
thwest][North America][250000.0000][5200475.2313][1439156.0291]

[277][][Jillian][][Carson][][Sales Representative][517-555-0117][jillian0@advent][1][80 Sunview Terrace][][Duluth][Minnesota][55802][United States]
[Central][North America][250000.0000][3857163.6332][1997186.2037]

[278][][Garrett][R][Vargas][][Sales Representative][922-555-0165][garrett1@adven][0][10203 Acorn Avenue][][Calgary][Alberta][T2P 2G8][Canada][Cana
da][North America][250000.0000][1764938.9859][1620276.8966]

[279][][Tsvi][Michael][Reiter][][Sales Representative][664-555-0112][tsvi0@adven][1][8291 Crossbow Way][][Memphis][Tennessee][38103][United States
][Southeast][North America][300000.0000][2811012.7151][1849640.9418]

[280][][Pamela][O][Ansman-Wolfe][][Sales Representative][340-555-0193][pamela0@a][1][636 Vine Hill Way][][Portland][Oregon][97205][United Stat
es][Northwest][North America][250000.0000][.0000][1927059.1780]

[281][][Shu][K][Ito][][Sales Representative][330-555-0120][shu0@adventure-works.
com][2][5725 Glaze Drive][][San Francisco][California][94109][United States][Sou
thwest][North America][250000.0000][3018725.4858][2073505.9999]

[282][][JosΘ][Edvaldo][Saraiva][][Sales Representative][185-555-0169][josΘ1@adve][0][9100 Sheppard Avenue North][][Ottawa][Ontario][K4B 1T7][Cana
da][Canada][North America][250000.0000][3189356.2465][2038234.6549]

[283][][David][R][Campbell][][Sales Representative][740-555-0182][david8@adventu][0][2284 Azalea Avenue][][Bellevue][Washington][98004][United State
s][Northwest][North America][250000.0000][3587378.4257][1371635.3158]


Sunday, July 26, 2009

Basic Perl file parser - useful for working with logs

Really I just need to remember how to do this:

#!/usr/bin/env perl
#yum log file
use warnings;
use strict;

open FILE, "/var/log/yum.log" or die $!;
while (<FILE>) {
my ($month,$day,$time,$action,$package) = ($1,$2,$3,$4,$5);
if( $action =~ /Installed/ ) {
my $suffix = 'th';
if( $day == 1 ){ $suffix = 'st'; }
if( $day == 21 ){ $suffix = 'st'; }
if( $day == 31 ){ $suffix = 'st'; }
if( $day == 2 ){ $suffix = 'nd'; }
if( $day == 22 ){ $suffix = 'nd'; }
if( $day == 3 ){ $suffix = 'rd'; }
if( $day == 23 ){ $suffix = 'rd'; }

print "$day$suffix of $month at $time\n"
close FILE

Joining multiple PDF documents with Gostscript.

This really works.

I downloaded all the chapters of beginning perl as published here:

To do it in a painless way I first used curl to grab the html.
curl -o bp.txt

Then I used grep to grab the hyperlinks to pdf files and piped that into another file.
cat bp.txt | grep -o "<a.*pdf"> bp2.txt

Then I used sed to clean up a little bit.
cat bp2.txt | sed "s/^<a href=\"//g"> bp3.txt

Then I used wget to download each pdf.
for line in `cat bp3.txt`; do wget $line; done

So now I had a whole bunch of pdf files that together make up one book. A quick hunt on google produced this guy.

And I was away laughing.

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=beginning-perl.pdf 3145_Intro.pdf 3145_Chap*.pdf 3145_App*.pdf 3145_Index.pdf

Sunday, July 5, 2009

Samba File Sharing to Windows ( Includes Vista )

I found this:

Here are the main points:

Install Samba

yum install samba samba-client

Configure Samba ( as root )

# vim /etc/smb.conf

Add a workgroup name under the [globals] section.

Add your fileshares at the end of the file.

path = /media/TerraByte
public = yes
writable = yes

This will create a writable share. File permissions in linux must match. Ie: (dwrx-dwr-dwr ).

If your drive is an NTFS formatted drive, these permissions can not be applied. It doesn't matter though because it still works.

Set up samba users. Users must already exist as users on your linux system. They must be valid users. The password does not need to match. There are a bunch of warnings that can be ignored.

# smbpasswd -a username
New SMB password:
Retype new SMB password:
account_policy_get: (warnings ignored)
Added user username.

Start the samba service and enable it in chkconfig levels 3 and 5.

Enable samba in the firewall of the linux box.

SELINUX - I don't use it at home so I have quoted direct from the webpage for reference.

SELinux has significant control over restricting different parts of Samba. Run system-config-selinux. Please read lines #23 - #51 in /etc/samba/smb.conf for a better explanation. Alternatively, you can run:

[mirandam@charon ~]$ system-config-selinux

Go to Boolean and type 'samba' in the Filter (without quotes).

Alternatively, you can ignore SELinux at this point and try to access your shares in Windows and SELinux TroubleShooter should give an automatic pop-up in GNOME explaining what is wrong. If you follow those recommendations you most likely will be more secure.

For any changes made above to the SELinux settings or smb.conf, it is recommended to restart Samba.

Monday, June 15, 2009

Having fun with LaTeX

LaTeX - Pronounced Lay-tec ( as in tech ) as in don't pronounce the X like X-Ray but rather as a soft c as in tech.

Ok so now we have the way to say it under control, I thought I might describe it a little. LaTeX is a document mark-up language based on Tex. ( just look this stuff up on Wikipedia cos I am too lazy tonight to starting collecting references and formatting them correctly and worrying about how the document is structured etc... ) Its all so boring - Enter LaTeX to save the day.

On Fedora you can download the LaTeX plugin for Gedit and start editing your next book, thesis, report or article. Basically it provides a mark-up language not unlike that provided by MediaWiki. It lends itself nicely to multiple document type conversions as the content formatting is described rather than embedded.

LaTeX takes this one step further by handling all your references inside a separate file compiled by the companion application called Bibtex. The Gedit plug-in will actually prompt you for all the reference fields then when you cite a reference in your document, LaTeX will format the bibliography correctly according so some kind of standard.

It's been a while since I was in tertiary education but my good friend wrote his thesis with it and he actually has a PhD.

So there you go.

Saturday, May 2, 2009

Orcon owns iServe owns Kiwiwebhost

It was announced ( on the 1st May that
Orcon have acquired iServe. iServe are the parent company for
Kiwiwebhost. It seems like a remarkable coincidence that in the days
leading up to this acquisition, Kiwiwebhost rushed into upgrading their
servers from php4 / MySQL 4 to php5 / MySQL 5.

Besides my moaning about all the hard work I had to suddenly do to get
my one osCommerce website ready for this upgrade, I am ultimately
pleased that the upgrade was made. PHP5 offers so much more in terms of
Object Oriented Programming ( OOP ) as well as increased security.
Kiwiwebhost have also turned Register Globals off. This closes a
fundamental security hole.

So well done to Kiwiwebhost for implementing a large upgrade in a short
period of just two days with outages amounting to less than 12 hours per
server that was being upgraded.

Thursday, April 30, 2009

osCommerce & Register Globals

What happens when your web host finally get's around to upgrading to php5 and MySQL 5? Here is what happened to me in order:

1. Rejoice because finally your website is hosted according to industry standards.
2. Panic because you are unprepared.
3. Worked through the night to get the website updated.

In order to migrate an osCommerce website from php4 to php5 there is really only one thing you need to worry about and that's a little "feature" in php called, Register Globals.

Register Globals makes every variable contained in the URL, POST, SESSION and ENVIRONMENT directly available in every script. What this means is that with register globals turned on, you can write a webform that posts a variable to a script and that script can refer to the variable in the POST by name. For example:

** Example script to show what happens when register globals is turned on.
** A form will submit POST data to this website as follows:
** String $_POST['name'];
** Int $_POST['age'];
echo "<h2>Thank you for telling me your name and age.</h2>";
echo "With register globals turned on we can do this:<br/>";
echo "Your name is: " . $name . "</br>";
echo "You are " . $age . " years old.";

Now with register globals turned off, you need to do it this way.

** Example script to show what happens when register globals is turned on.
** A form will submit POST data to this website as follows:
** String $_POST['name'];
** Int $_POST['age'];
echo "<h2>Thank you for telling me your name and age.</h2>";
echo "With register globals turned on we can do this:<br/>";
echo "Your name is: " . $_POST['name'] . "</br>";
echo "You are " . $_POST['age'] . " years old.";

PHP does have an neat function called, "extract" which will take all the variables in and associative array. It works like this:

** As before we have a post that looks like this:
** String $_POST['name'];
** Int $_POST['age'];
** We want to create variables out of the $_POST array keys and make the values the values
** if you catch my drift.
echo "<h2>Thank you for telling me your name and age.</h2>";
echo "With register globals turned off we can do this:<br/>";
if( isset ( $_POST ) && !empty( $_POST ) ) {
extract($_POST, EXTR_SKIP);
echo "Your name is: " . $name . "</br>";
echo "You are " . $age . " years old.";
} else {
echo "You did not post any data.";

So you can see where I am going with this. The first thing I needed to do was to make sure that all the "registered global" variables were first caught and made available in the above way.

osCommerce Session handling
It quickly became apparent that I was not going to get anywhere until I had the sessions stuff sorted. At this stage I gave up working this out for myself and searched for help. I found an excellent resource called: Magic SEO URL for osCommerce (osCMax)

There were a couple of other pitfalls:

1. root/admin/includes/classes/upload.php has a line that sets "$this = null;" PHP 5 objects to this ( excuse the pun ) so the correction is fairly simple. Just comment it out. I did play with unset( $this ) but found that to cause some other difficulties.

2. The variable $PHP_SELF is referred to many times in osCommerce code. As this is a registered global it will not be available to your code after the upgrade. You must set this variable in application_top.php like this:


Other things that did not happen to me but might happen to you.
MySQL upgrade breaks all your queries. This is quite a common problem that I have encountered before but not recently. MySQL 5 requires the correct bracketing of clauses in the from statement of a query. Especially with regards to left joins. Search for this in the contributions section of osCommerce.


Sunday, April 26, 2009

Recycling old computers

I have an old PIII at home with 256Mb Ram and a 20Gb hard disk. Graphics is nothing to write home about and it will not support Vista or KDE 4.2.

I know there are many, many blog posts on the internet that discuss this so I will simply add to the general wash.

Ubuntu Server:
  • File server with samba
  • Apache webserver with ( free dynamic IP to Domain Name resolution ) - This can be useful if you are a freelance website designer / programmer and you need to publish draft websites for your clients prior to going live.
Xbuntu Desktop:
  • Install Childsplay - a very basic suite of games that are designed to develop mouse and keyboard familiarisation in a fun and easy to understand environment. - In fedora this was just as simple as, "yum install childsplay"
  • Install the Mame Emulator and download roms for some of those neat and safe for kids arcade games that you played in the 80's at your local cornershop or arcade.
  • If you have an XBOX controller - install the drivers for the XBOX and purchase an adaptor for the controller to plug into your USB. Then those mame arcade games start to look more appealing.
Windows XP ( If you have it ):
  • Childsplay is available for both Windows and Linux so get the windows version up and running.
  • Get Mame32 installed and the XBox controller drivers. My XBOX Gamepad to USB adapter came with a disk with drivers to install for XP.
  • Head down to noel leeming and buy some kids games. They don't need anything more than a 75mhz PC and 64mb ram. They are still fun to play and will keep your kids occupied.
  • Windows XP can also be used for accounting software if you have a small business - Cashbook Complete for example.

I am sure there are folks around who have loads of other suggestions but these are the ones I have tried / thought about.

I know this has always been a linux related blog, and this small bit on Windows does seem out of charicter. The reality of it is that even though I use linux exclusively at home, my family do not...

Friday, April 10, 2009

Write .NET applications on Mono and use them in Windows

I am no professional .NET developer but I thought I would have a crack at a simple application written on my Fedora 10 in the Monodevelop IDE and then run the same exe it compiles in a Windows XP. It took a while but I got there in the end and in retrospect it was not too hard. Just a few dependancies, a short forum-search for a solution to a small problem.

Here is what I did:

1. Install mono, monodevelop and gtk-sharp ( GTK# ):
The monodevelop IDE provides a gui designer for gtk#. So I thought I would try this out and see how I could get that working in windows too. In Fedora I just ran the following:

# yum install monodevelop gtk-sharp*

As usual I let yum decide dependancies for me.

2. Start monodevelop and create a new solution:

Select the C# templateand then pick Gtk# 2.0 Project
Under Solution name: type "tutorial" and under Name: type "myGuiApp" to create a Gtk# GUI application under the folder {$HOME}/Projects/tutorial.

Click Forward and select your Target GTK environment and click Finish.

There will be two files in your solution: Main.cs and MainWindow.cs. You will only need to work on MainWindow.cs

3. Design your application in Monodevelop:

This will be a very simple application. Only a little more advanced than Hello, World.
Double click on MainWindow.cs to start editing the Window. Monodevelop has already provided you with a basic GUI shell to work with.
Beneath the source code window on MainWindow.cs you will see two buttons: Source Code and Designer. Click the Designer button to start dragging and dropping your tools onto your palette.

Seeing as though you are using Gtk# to create this GUI there is something that you should know before continuing. It requires the use of containers to handle the positioning of widgets. For the purposes of this tutorial I will just use the Fixed Container.

Drag a Fixed container onto your pallet first. Then drag the following widgets onto the pallet. Position them something like the next screen shot.

3 Labels
2 buttons
1 entry box

Resize your pallet to suit.

Above the designer pallet you will see a dropdown list that can be used to select each element on your pallet starting with the window itself. Select each of these and then adjust their properties as below:

MainWindow: Window Properties: Window Title = "My Gui App"
label1: Label Properties: Label = "Welcome to My GUI APP"
label2: Label Properties: Label = "Your name please:"
label3: Label Properties: Label = "Hi there, "
button1: Button Properties: Label = "Greet!"
button2: Button Properties: Label = "Close"

You may have to rearrange things a bit to get everything fitting on your screen. Now it should look something like this:

4. Add signal handlers to the buttons

Click button1 ( now labelled, "Greet!" ) and under the properties pallet select the Signals tab. Next under the Button Signals double click on the Clicked signal. Monodevelop will automatically create a handler called OnButton1Clicked for you.

Click button2 ( now labelled, "Close" ) and do the same as you did for button1.

5. Time to start editing some code:

Click the Source Code button to view the source code for MainWindow.cs. You will find two new functions called:

protected virtual void OnButton1Clicked (object sender, System.EventArgs e)

protected virtual void OnButton2Clicked (object sender, System.EventArgs e)

Edit them to look like this:

protected virtual void OnButton1Clicked (object sender, System.EventArgs e)
label3.Text = label3.Text + entry1.Text;

protected virtual void OnButton2Clicked (object sender, System.EventArgs e)

6. Compile:

Click the build button and try your application out. It should compile without any difficulties at all. Should being the operative word. If your app did not compile do not proceed. Get it working first!

7. Getting Windows XP ready:

Getting Windows ready was as simple as installing the Mono package for windows. It includes a command prompt mode. Also you can create shortcuts to your mono apps that execute the mono launcher to launch your code. A bit like the java stuff.

I have yet to get it to work effectively on both linux and windows without having to first install the mono environment on both. I had thought that mono applications written on Linux could be migrated over to Windows without the mono libraries present.

I have yet to test how a windows app written for .NET v2 will port over to Linux. Again I think that without winforms it will not work. It might work for a command prompt application. But that's about it.

Anway here it is working just fine in my qemu windows xp vm.

Thursday, April 9, 2009

Blogger Templates

I have changed the template only slightly. It seems that this default denim template also has a "wide" option. The colours and widgets remain the same. The only difference is that source code can now be read more easily as the layout will stretch with the browser.

Wednesday, April 8, 2009

CSS Floating Box Model

A simple floating box model example showing how to "float" div elements within another div element. This example includes boxes that float left and boxes that float right. It is easy to imagine how one could beef up the aesthetic quality of these floating boxes with rounded corners or varied background colours or patterns. The boxes used here are for demonstration purposes only.

<title>Floating Right and Wrapping</title>
#maincontent {
width: 600px;
margin: 0px auto;

.wrapcontainer {
padding: 5px;
border: 1px solid #777777;
margin: 5px;
display: block;
font-family: arial,helvetica,sans-serif;

.sidebar-right {
float: right;
border: 1px solid #777777;
padding: 5px;
margin: 5px;
display: block;
width: 210px;
font-family: arial,helvetica,sans-serif;

.sidebar-left {
float: left;
border: 1px solid #777777;
padding: 5px;
margin: 5px;
display: block;
width: 210px;
font-family: arial,helvetica,sans-serif;

h3 {
font-family: arial,helvetica,sans-serif;
color: #333333;

p {
font-family: arial,helvetica,sans-serif;
color: #333333;

<div id='maincontent'>
<h3>Wrap text around object floating right.</h3>
<p style='width:600px; display:block;'>
Below you can see three block level elements. They are #maincontent on the outside
#wrapcontainer which inherits it's width from #maincontent and floats to the left
of #maincontent. The last block level element you can see is called .sidebar-left|right. It
floats to the right of #maincontent.
<div class='wrapcontainer'>
<div class='sidebar-right'>
This text will appear inside the sidebar and will be constrained by the
width of the sidebar.
This text will appear inside the sidebar and will be constrained by the
width of the sidebar.
This text will appear inside the sidebar and will be constrained by the
width of the sidebar.
Te, vel dolor, dignissim volutpat, exerci wisi laoreet euismod et enim nulla. Vel ut eum et lobortis nisl consectetuer luptatum ad blandit, veniam dolore consequat veniam. In dolor iriure eros in odio ex, ea hendrerit, molestie, et zzril. Et facilisis, eu tation tation iriure minim et velit praesent dolore autem esse dolore dignissim, dolore blandit duis ex nisl praesent in exerci in nibh.
Facilisi veniam feugait dignissim zzril ea esse nostrud dolore veniam sit iriure te tincidunt feugait sit ut ipsum ullamcorper, facilisi minim qui, et facilisis vulputate. Ex illum consequat vulputate et velit dolore vel, consequat dolor laoreet dolore autem aliquip, suscipit, facilisi tation ullamcorper praesent minim, te eros dignissim consectetuer. Blandit, ut hendrerit exerci vel odio, iriure, lobortis vel eros enim, eu tation laoreet volutpat at aliquam. Wisi facilisis autem consectetuer vel, duis, accumsan delenit augue, aliquip qui vero hendrerit molestie euismod.
<div class='sidebar-right'>
And another<br/>
This text will appear inside the sidebar and will be constrained by the
width of the sidebar.
Feugait veniam ullamcorper iriure diam in duis zzril, in in, enim accumsan ut, iusto elit dolore feugiat odio luptatum ad tincidunt adipiscing, nulla. Commodo vulputate velit et, dolor minim blandit nonummy ex at blandit augue nostrud magna nonummy facilisis eu consequat. Lobortis odio in et ullamcorper molestie consequat wisi esse feugait dignissim feugiat ut et at, nisl nisl in, molestie, qui. Ad dolore, lorem minim vel consequat luptatum vero illum odio et ex augue. Vulputate euismod zzril commodo nulla amet exerci feugiat eum duis, autem nulla nostrud minim, te te, illum dolore nisl feugait consequat elit blandit. Hendrerit hendrerit ex dolor commodo, suscipit exerci ipsum ipsum dolore, volutpat.
Wisi volutpat at aliquam, hendrerit facilisis autem consectetuer vel, duis. Suscipit delenit augue, aliquip qui vero hendrerit molestie euismod velit, feugait nibh zzril ea delenit molestie dolore veniam quis, odio ut delenit facilisis nostrud iriure. Feugiat illum iriure in velit veniam sit tation commodo nulla facilisi consequat veniam nibh facilisis eu. At adipiscing eu lorem ipsum consequat aliquip vero blandit praesent.
<div class='sidebar-left'>
And another<br/>
This text will appear inside the sidebar and will be constrained by the
width of the sidebar.
Et in et ullamcorper molestie consequat wisi esse feugait dignissim feugiat ut et at, nisl nisl in. Nisl, qui, ut dolore, lorem minim vel consequat luptatum vero illum odio et ex augue esse euismod zzril commodo nulla amet exerci feugiat. Dolore duis, autem nulla nostrud minim, te te, illum dolore nisl feugait consequat elit. Ut erat hendrerit ex dolor commodo, suscipit exerci ipsum ipsum dolore, volutpat ea, wisi eum vulputate zzril.
Feugait veniam ullamcorper iriure diam in duis zzril, in in, enim accumsan ut, iusto elit dolore feugiat odio luptatum ad tincidunt adipiscing, nulla. Commodo vulputate velit et, dolor minim blandit nonummy ex at blandit augue nostrud magna nonummy facilisis eu consequat. Lobortis odio in et ullamcorper molestie consequat wisi esse feugait dignissim feugiat ut et at, nisl nisl in, molestie, qui. Ad dolore, lorem minim vel consequat luptatum vero illum odio et ex augue. Vulputate euismod zzril commodo nulla amet exerci feugiat eum duis, autem nulla nostrud minim, te te, illum dolore nisl feugait consequat elit blandit. Hendrerit hendrerit ex dolor commodo, suscipit exerci ipsum ipsum dolore, volutpat.
Wisi volutpat at aliquam, hendrerit facilisis autem consectetuer vel, duis. Suscipit delenit augue, aliquip qui vero hendrerit molestie euismod velit, feugait nibh zzril ea delenit molestie dolore veniam quis, odio ut delenit facilisis nostrud iriure. Feugiat illum iriure in velit veniam sit tation commodo nulla facilisi consequat veniam nibh facilisis eu. At adipiscing eu lorem ipsum consequat aliquip vero blandit praesent.

Wednesday, March 25, 2009

Learning Linux at 84

I am sure I have never encountered a person at the grand age of 84 learning Linux before today. As it turned out I sold a Fedora 10 DVD from my website ( ) to a gentleman in Auckland who needed some help. Usually I shy away from supporting Linux unless it is something related to the media I sell. In this particular case I needed to get involved because I needed to determine where the problem my customer had came from.

We got on the phone together and I ran up a fresh install of Fedora 10 on a VMWare Virtual machine so I could guide the customer through the install.

Considering the initial failure as the customer described it was most likely related to Anaconda, I decided that a text install might be more successful. Fedora keeps the text installer hidden. You have to hit the TAB key to edit the boot parameters when the DVD boots up and add the word "text" at the end of the line. After that the DVD boots into a TEXT only installer.

We had a scary moment at the partitioning stage where I wasn't 100% sure that we were not going to destroy the windows partition that the customer wanted to keep for dual booting. My customer was very understanding when I said that I wanted no responsibility for the loss of any important data... Fortunately all went well and the grub installer found the "other" OS which we changed to be Windows.

The last thing that needed to be done, which I have had to email to the customer because we have long since hung up and which I only found out after my version of the install was complete was set the run-level back to 5 and manually create a user for him to login with on the console.

Steps to complete this last process:

Log into the console as root.

# nano /etc/inittab

Scroll to the end of the file and change the line, "id:3:initdefault:" to "id:5:initdefault:"

# groupadd peter
# useradd -g peter -m -s /bin/bash peter
# passwd peter
Enter password
Confirm password

And that's about the end of it. After the machine reboots you will be able to log in as peter with the password you typed in the above commands.

Wednesday, March 18, 2009

Simple Cluster with Heartbeat

Following on from my previous post about setting up a reverse proxy in Fedora 10, I now delve into high availability. The plan here is to create two reverse proxy servers and cluster them together in an Active / Passive configuration with automatic fail-over.

So here is our trusty network diagram:

You will notice the shared IP and Proxy02 with connected to Proxy01 with the cross-over cable.

You need the cross-over cable for the heartbeat keep-alive messages. As I am using VMWare I have used the HOST ONLY network configuration for the second nics on the servers thus simulating a physical cross-over cable.

Here is the network configuration on each proxy server:

eth0- ( same network and subnet as the client )
IP =
HOSTNAME = proxy01.latham.internal

eth1 - ( different network and subnet as the client )
IP =

eth0- ( same network and subnet as the client )
IP =
HOSTNAME = proxy02.latham.internal

eth1 - ( different network and subnet as the client )
IP =

In my environment I have actually used DHCP and statically assigned leases for the eth0 nics on my proxy servers.

You will need to ensure the availability of a shared IP address for the eth0 nics. In my case I chose No other server should own this ip address.

Next up we will install heartbeat on the proxy servers.
As usual in Fedora we leverage the excellent package manager ( YUM ) and install it:
# yum install heartbeat
Once heartbeat and all required dependencies are installed you will need to edit some configuration items. First lets start with the basics in preparation for Heartbeat managing the resources.

NOTE: At the time of writing this tutorial I have not worked out the required SELINUX directives so have turned SELINUX off. I recommend getting Heartbeat working with SELINUX turned on.
# setenforce 0

1. Ensure that the Apache web-service does not auto-start:
# chkconfig httpd off

2. Ensure that httpd will listen on the correct IP address. This will be the shared IP address. In my lab this is
# vim /etc/httpd/conf/httpd.conf
[ update the listen directive to read: ]

Heartbeat arrives totally unconfigured. You have to create 3 files in order to make it work. These files live in /etc/ha.d and are called:
  • haresources
  • authkeys
Here follow my examples: IMPORTANT: These are identical on both servers.
bcast eth1
keepalive 2
warntime 10
deadtime 30
initdead 120
udpport 694
crm no
auto_failback no
node proxy01.latham.internal
node proxy02.latham.internal

proxy01.latham.internal apache::/etc/httpd/conf/httpd.conf

auth 1
1 crc

The authkeys file must be made secure with:
# chmod 600 authkeys

The crc method of authenticating is fast but insecure. The insecurity of it is offset by the security of the cross-over cable. In a more paranoid or less secure environment you might consider either md5 or sha1.

Make sure httpd is stopped on both nodes:
# service httpd stop
Start heartbeat on both nodes:
# service heartbeat start
Note that there might be a message stating that a resource is stopped. This will be becuase at the time of starting heartbeat the httpd resource was stopped. In a short while heartbeat will start httpd for you.
Now try to browse the example html page that you configured in your reverse proxy but with the shared ip address this time, and note in the access logs for proxy01 the traffic.
Try removing proxy01 from the cluster with
# service heartbeat stop
and note that in a short while proxy02 will take over the shared IP address and start httpd.

Other tests I have performed:
1. stop httpd on the primary node and watch it start up again after 30 seconds.
2. shut the primary node down altogether and watch the secondary node take over.
3. Bring the primary node back into the cluster and watch it take over the shared up and start httpd while stopping httpd on the secondary node. ( AUTO FAIL_BACK = yes ) - This feature seemed not to work. All my failback testing resulted in a failback regardless of this setting.

Other considerations:
1. sync your webserver files.
2. test ssl connections.

Monday, March 16, 2009

Clustered Reverse Proxy with Fedora

I was given the enviable task of setting up a reverse proxy in Fedora.

A reverse proxy is a piece of software that is installed on a device that has network access to an external and internal network. The proxy acts as a bridge between the two networks. A normal proxy as installed in most company networks allows all users on the internal network to access the external network. A reverse proxy allows clients on the external network to access services hosted on the internal network. It can be installed on the front end of the network and will proxy specified traffic through to the internal network.

Here is a diagram of my lab network. In this example we can see:
  • Multiple clients are connecting to the proxy cluster. ( more on clustering in the next article. )
  • Only one node in the cluster has possession of the shared IP address.
  • The Apache web service on the proxies are configured to listen on the shared IP address.
  • The host web server behind the resource zone is serving traffic to the active node.
  • All servers shown in this lab were built from the Fedora 10 Installation DVD. Required dependancies were installed using YUM. It helps if the machines can be built while connected to a network with access to the internet.

Configuring the
Reverse Proxy Server.

  • DHCP or Statically assigned.
  • Must be on same network or accessible by the clients.
  • In VMWARE use "Bridged" so you can access it from your host.
  • Statically assigned.
  • Cross Over cable ( in VMWARE use "Host Only" )

  • Install the basics and the apache webservice. In Fedora 10 mod_proxy is already included and ready to be enabled.
  • Install gcc ( yum install gcc ) Required to compile the mod_proxy_html module.
  • Follow these procedures in LISTING 1 to get "mod_proxy_html" installed. Mod_proxy_html is required for rewriting URL links in the web pages served from behind the resource firewall. All links will need to point to the shared ip or hostname.
  • Edit /etc/httpd/conf/httpd.conf. After all the LoadModule directives ensure that these two lines appear.

(/etc/httpd/conf/httpd.conf )
Proxy Configuration - httpd.conf: LoadFile /usr/lib/
LoadModule proxy_html_module modules/

wget ""
yum install httpd-devel libxml2 libxml2-devel
apxs -c -a -I /usr/include/libxml2 -i mod_proxy_html.c

The apxs command above will insert the "LoadModule" directive for prxoy_html_module. I needed to edit the path to read, "modules/"

Restart httpd on your proxy servers after installing mod_proxy_html with:
# service httpd restart
Create a reverse proxy config file in /etc/httpd/conf.d/reverse_proxy.conf.

Here is my example: ( read up on the reasoning here: )
ProxyRequests off
ProxyPass /test/
ProxyHTMLURLMap /test

ProxyPassReverse /
SetOutputFilter proxy-html
ProxyHTMLURLMap / /test/
ProxyHTMLURLMap /test /test
RequestHeader unset Accept-Encoding

RewriteEngine on
RewriteRule ^/test$ test/ [R]

The rewrite rule at the end will allow for any urls that miss the trailing slash on directories. It will add a trailing slash in automatically.

Restart httpd with:
# service httpd restart
Create 2 html pages on the internal network. One should link to the other using the IP address of the internal httpd server so we can see how the HTML links are rewritten.

My next instalment will cover how to create a simple auto-failover cluster using heartbeat from the Linux HA Project.

Sunday, March 8, 2009

Commandline to reliably burn an ISO ( On My Machine )

In order to reliably burn an ISO image to CD or DVD there are a couple of options that need to be set. That's if you are planning on using terminal commands ( command line tools ) to do the job.
  1. The disk must be written in DAO ( Disk At Once ) also known as SAO ( Session At Once )
  2. The disk must be written in as slow a speed as possible. On my PC that is about 8x for a CD and 4x for a DVD. Remember speed ratios differ between DVD and CD.

My Scripts: ( saved in /usr/local/bin )

[dave@fedora10 bin]$ cat burn-cd

#burn CD
# Usage - Enter full path to distro here.
/usr/bin/wodim dev=/dev/sr0 driveropts=burnfree fs=14M speed=9 -dao -v -eject $1
[dave@fedora10 bin]$ cat burn-dvd

#burn CD
# Usage - Enter full path to distro here.
/usr/bin/wodim dev=/dev/sr0 driveropts=burnfree fs=14M speed=4 -dao -v -eject $1
The options for wodim ( cdrecord as it is called nowdays )
Note the Speed, Burnfree and -dao options. -dao tells Wodim that you want to burn the ISO image in one go. No separte tracks.

Thursday, February 26, 2009

Helping out folks with internet access difficulties.

I subscribe to the NZLUG ( New Zealand Linux Users Group found at ) mailing list and received a very interesting item in my inbox this evening.

Internet Assist North Shore are looking for ways we can help out families who do not have the wherewithal or sufficient finances to get on-line. The idea is that we donate old hardware with opensouce only software and operating systems along with our time for installation, setup and training if required.

Another idea was also put forward to provide the actual internet access. However that is possible. I think they are looking for ideas.

One option might be through sponsorship. Corporates looking to provide their services might, for the extra publicity we could maybe provide, cover the $25.00 a month for a year or even 6 months to get folks on-line and up and running.

It might be tricky to work out who qualifies...

Anyway - those are my ideas... For now anyway. Check them out at:

Wednesday, February 18, 2009

Flock - Social Web Browser

Those of you who are into social networking and like to keep up to date with your feeds, facebook, twitter, youtube and anything else, then you might like Flock.

Flock is a mozilla based portal into all of these services.  It saves your account login data and allows you to both browse and social network at the same time from the same application.  Rather than all your services in multiple windows, you have them in one application.

I recommend a large screen though.  Wide screens are especially suitable for thos wide sidebars.

Check out Flock at

There is a windows and a linux version.  I didn't bother to check if there was a mac version.
Blogged with the Flock Browser

Tuesday, January 20, 2009

Linux Security

I would like to share this post on Linux Security. I would place it in my shared items but I thought that if I left it there it would go largely unnoticed.

The author has written a fantastic entry about the User effect on security within a Linux environment. He makes points about users running arbitrary code as root, installing unsigned packages and a lot more. It is well worth a read!

I would like to note that I am merely trying to introduce a great piece of writing by another blogger.

Saturday, January 17, 2009

Bash Progress Bar

Ever wanted to show a progress bar on your bash scripts? I am talking specifically about the progress of file transfer or raw read scripts. It might be easier to explain with an example:

I have a script that reads raw data from a CD or DVD ROM disk and pipes that data to md5sum or sha1sum to find if the data on the disk matches the published md5sum or sha1sum checksums published by the vendor. I download ISOs and verify them before I send them to my customers.

I wanted to have the script show a progress bar so I started searching...

Here is how I have implemented clpbar

Installation instructions ( Fedora 10 x86_64 )
  1. Download and install clpbar ( bar-1.10.9.tar.gz ) -- See references at the end of this script.
  2. tar xvfz bar-1.10.9.tar.gz
  3. cd bar-1.10.9
  4. ./configure
  5. make
  6. su -c "make install"

Usage example


# Start with verifying CDs

# pass the type of checksum into the script. (md5sum|sha1sum)

#Find details of the device
blocksize=`isoinfo -d -i $device | grep "^Logical block size is:" | cut -d " " -f 5`
if test "$blocksize" = ""; then
echo catdevice FATAL ERROR: Blank blocksize >&2
exit 1

blockcount=`isoinfo -d -i $device | grep "^Volume size is:" | cut -d " " -f 4`
if test "$blockcount" = ""; then
echo catdevice FATAL ERROR: Blank blockcount >&2
exit 1

command="dd if=$device bs=$blocksize count=$blockcount conv=notrunc,noerror status=noxfer"

# find the mount point of the disk. In fedora we need to know this to get the exact
# size of the disk in bytes. Note: /dev/sr0 is the optical disk drive on my system.

mountpoint=`mount | grep /dev/sr0 | sed "s/\/dev\/sr0 on //g" | sed "s/\stype.*//g"`

# find the expected size of the media. In order for bar to display a progress
# bar we need to know the expected size in bytes.

expected_size=`du -bs "$mountpoint" | sed "s/\s.*//g"`

# execute the command to read the disk and
# pipe through bar with the size option set and
# pipe through md5sum or sha1sum

result=`$command | /usr/local/bin/bar -s $expected_size | $checksumtype`

# get the checksum only. ( get rid of the '- ' on the output. This is required
# for the python tool that actually executes this script and compares against
# my database of checksums. -- I use python to call this script and compare the results
# against those in database. Another option would have been to bash script the mysql portion too.

checksumresult=`echo $result | cut -d " " -f1`

echo $checksumresult


Tuesday, January 6, 2009

The New Paymex

I had a crack at installing Paymex on my osCommerce website this evening. I will try to summarise the experience:

Paymex provide an osCommerce module for download from their website. It is mind numbingly simple to install. A simple upload of files is all that is required. There is absolutely no php editing required. This is always a plus for me. osCommerce code is painful enough and in a production environment any update that does not require php code editing is very useful.

5 out of 5 for installation.

There is only one item of identification required by the Paymex module config. A business id. This looks remarkably like a windows uid. I just copy pasted it from the Paymex website while logged in there.
There is the option to have the paymex module enabled or disabled, Test mode or Production mode, set the acknowledged order status and the sort order.

So not much to configure really and very simple to understand.

4 out of 5 for configuration. Not enough detail. Concerns around security especially with regard to certificates on IPN.

Functionallity ( osCommerce Module Specific )
I would have liked to see something there about enabling or disabling IPN ( instant payment notification ) and the URL for the IPN. This made me wonder about what Paymex do about IPN. Those of you with osCommerce websites you will know that IPN is critical. The site has to be notified on successful completion of a sale. Without it the products stock count doesn't get updated and the order is left in a pending / preparing state.

Paymex offer do provide autmatic IPN for either RETURN URL, HTTP POST or HTTP GET. The provided osCommerce module has the IPN option set to RETURN URL. This means that if the web browser is closed or the customer navigates away from the site, then the site will NOT BE NOTIFIED of the successful completion of a sale. The merchant will, however, still receive an email from Paymex with information on the sale so all is not lost.

2 out of 5 for Functionality. Once the osCommerce module included HTTP POST based IPN and details on how ssl is implemented throughout the IPN process, I will gladly upgrade this to a 4 or a 5 out of 5.

Sadly, Paymex has a very poor reputation right now. I am not really convinced that it is all deserved. From what I understand, one of their merchants was involved in some kind of fraud and the resulting card scheme charge-back brought the business into massive debt. Unfortunatley the damage has been done. The problem for merchants was that their funds in the Paymex account was compromised.

To fix the situation the new Paymex ( not sure if its new owners or what ? ) have done a deal with a big New Zealand bank to set up a trust account that will hold the merchants' funds. Are they saying that this bank will secure all funds in that account?

Lets hope that the merchants' money will actually be deposited there. I wonder if merchants can request from the bank, a statement showing the funds in the trust account.

I will be watching Paymex closely and deciding if they should process my transactions.

I do like the simplicity of their solution. I also like that they are in New Zealand.