<<< Back


Unless noted otherwise all there programs are released under MAiL (Max Artistic imaginary Licence). This licence state that "you may freely use these programs and are free to contribute and distribute them", but that the author was to way too lazy to include/read through/understand the GPL, Perl Artistic Licence or something like that. So that is why they are under MAiL and not a better one. Essentially MAiL is the free, lazy license. Don't complain, they are free!




Belt (Freshmeat entry) is a small "menubar" that works as the "belt " normally found in MacOS. It has a lot of configuration options and can use multiple configuration files if you want several belts. It is really intended for the dynamic menusystem we have here at the School of Electrical Engineering at the Royal Institute of Technology and thus want to display icons for all program modules that have registered that they want to have an entry, but I use a static belt. If you want to know more, please read the source/documentation. Below is a screenshot.

The license is now BSD-style, see full license at the top of the program.

It is written in Perl/Tk and should run on any standard Perl/Tk installation. It is configured with a simple text file called menu.conf. There is an example of how a menu.conf-file might look like.

The full documentation is contained within the program itself and available with belt --help. The documentation is POD (Plain Old Documentation) so that it is easy to convert into manpage or any other format like HTML for example.

The special arrow-icons are included in the code of belt itself and may be extracted with the --extracticons switch. They are also available in a separate tarball for convenience. You can also get these versions in a half-scale (24x24) format but they are almost too small to see :-).

People have also asked me for the icons that are seen in the screenshot. I have not made these. They are collected from various sources on the net and found on my local system. You can browse the archive or download them all as a tarball.

I have also gotten questions about which window manager to use together with Belt. You can use any you like. Personally, I use Belt together with wm2 or fvwm2 (with my conf CleanStyle).


This is a small program that uses convert (from ImageMagick) to convert a picture from any format to a message that can be sent using Zephyr. It is in it's initial stage and is expected to have more than it's share of bugs.


A small program that show you if you have any unread messages in your subscribed newsgroups. I made it as an answer to a posting in a local newsgroup and it is very slow.


This is a program that I use to generate numbers, mainly when I want to do a shell loop or use wget to fetch many files with similar names. It is not that much to get excited about and the documentation is almost as large as than the actual code.


A small script to search for where manpages are located in the manpath. Sometimes several application packages supply their own version of commands or commands with the same names. In the modules environment this script was handy in locating where there where name clashes. Similar to the shell built-in command 'which'.


This is a small example of how to perform set operations of arrays in perl. This is NOT an effective way but it is a nice oneliner :-)

The running time is O(n2) whereas if you should code it with an intermediary hash you would instead get O(n).

#!/usr/local/bin/perl -w

use strict;

my @a          = (1, 2, 3, 7, 8, 9);
my @b          = (1, 3, 4, 5, 8);
my @both       = grep { my $e = $_;  grep {$e == $_} @b} @a;
my @inabutnotb = grep { my $e = $_; !grep {$e == $_} @b } @a;
my @inbbutnota = grep { my $e = $_; !grep {$e == $_} @a } @b;

print "A          = (" . join(", ", @a) . ")\n";
print "B          = (" . join(", ", @b) . ")\n";
print "BOTH       = (" . join(", ", @both) . ")\n";
print "INABUTNOTB = (" . join(", ", @inabutnotb) . ")\n";
print "IBBBUTNOTA = (" . join(", ", @inbbutnota) . ")\n";

And the output is of course:

A          = (1, 2, 3, 7, 8, 9)
B          = (1, 3, 4, 5, 8)
BOTH       = (1, 3, 8)
INABUTNOTB = (2, 7, 9)


Darkroom Log

This is a plain darkroom log for keeping track of enlarger and developer settings. Nothing special really, just something to have when you are working in the darkroom. This one was inspired by the darkroom log in Mastering Black-and-White Photography: From Camera to Darkroom by Bernhard J Suess (ISBN 1-880559-23-4). It's a great book. Get it.

Zone wheel

This is a small PostScript page that prints a handy utility when using a SLR camera with built-in spot meter for the Zone system. A description of how to assemble the wheel and, more importantly, how to use it will written in a near future. Meanwhile I would recommend The Negative by Ansel Adams (ISBN 0-8212-2186-8). If you read this book I think you can figure out how to use this wheel.

You are free to copy and share this utility among friends but if you want distribute a printed version of it, for example in a magazine, you must first get my written permission (basically I just want a copy of the magazine).


This is a small PostScript hack that produces a A4-size sheet that when printed on a duplex printer and folded results in a small booklet for noting exposure details when shooting roll film. Certainly not the most advanced out there, but it works.

The two versions are identical except for the language. In fact the files are identical except for a constant set to true or false depending upon which language you want. The folding instructions are included as comments in the file.

Roll Exposure Sheet

This is the companion to the Rollbooklet. Transfer the information from the booklet (which is used in the field) to this sheet and put it in your ring binder next to the negative sleeve and the contact sheet for easy access.

New Jiffy Calculator

While searching for data on exposure estimation in nighttime photography I stumbled upon a scan of the "Jiffy Calculator" by S.P. Martin. This was apparently published in a photographical magazine in the sixties. The scan wasn't too good and it was hard to get the numbers aligned. Also there were some strange numberings on the jiffy calculator. I combined this with data from the Ultimate Exposure Computer regarding EV:s.


Have you ever wanted something with thick lines visible through a sheet of paper when writing on a paper without lines? Here it is. Probably more interesting as an (simple) exercise in hacking PostScript.


I have done several projects which included PostgreSQL. Some also used the non standard patch PostgreSQL Hierarchical Queries which simplified coding quite a lot.


I have also the startup and backup scripts that I wrote for one system I administered at work and at home. Since the system at work used AFS and Kerberos I needed to get tickets when doing backups to move the backup into the AFS-tree (which we took nightly tape backups of). If you don't have AFS/Kerberos you can simplify it quite easily. This script ran nightly just before the tape robot started its work. The system back home is a standard debian system and it is probably this version that is most interesting to you.


I am by no means a Java programmer(TM). The code below originates from the time when I worked as an assistant teacher and are examples discussed in the lessons.


This is an example of storing data (words) in a trie tree. This example was written for the students that went to my class to illustrate how one could use a trie tree. It is rather verbose and intended as an example only!

This has now been updated with a printTrie() method printing all words in the tree and a printWordsStartingWith(s) method that prints all words starting with the prefix string s. Two more test programs are available to show these methods, respectively. Also the TrieNode class is not as verbose anymore as default. To print the ids of the nodes when creating them set the environment variable DEBUG to some value (other than empty). You can do this by java -DDEBUG=true TrieTest for example. Enjoy!


Another snippet of code from my class. This example takes a binary string (only zeroes and ones that is) as an argument and converts it to a decimal number. It has no check for overflows or anything, it was just meant to illustrate the principle of horners rule for converting between number bases.

The reverse procedure was given as a home excercise if I recall correctly.

Web utilities/programming

Here are some utilities and programs that might come in handy when dealing with the web, mostly server side.

HTML Scrubbing/Sanitizing

I have developed a few systems where users have had the opportunity to input text with limited HTML-tags, like forum boards, weblogs etc. Well, in reality the users could input any kind of HTML-tags and nothing was there to stop them from messing up the page, so I started thinking about writing something to fix this.

First of all, we would like to forbid the use of some tags and perhaps even some attributes in some tags, but allowing others. Also the problem with nested tags and unclosed tags are a nuisance. Ideally I wanted a filter, much like sed that would just filter out the unwanted stuff and close any open or nested tags.

But wait! I can't be the first one with this problem? Well, it seems like many people have reinvented the wheel and made their own solutions. I have seen several versions in Perl (for example the modules HTML::Scrubber and HTML::Sanitizer), PHP, etc. But few of these worked as a filter. Until I saw html_scrub by Scott McKellar. This was almost what I wanted. I wrote the configuration file found below that I find useful to filter out and only allowing a subset of tags.

Now I just had to adress the problem with open/nested tags. If I could find a similar tool I could use that as filter and pipe the result to html_scrub. Well, HTML tidy came to my rescue. I had to write my own configuration file for it to work properly as a filter. Initially I intended to write my own "tag closer", but it was much faster to just write a configuration file for tidy!

I have also compiled these two for use with Windows using MinGW. I never intend to use them on Windows really, since my web server is running Linux, but it might be nice to be able to filter anyway.

So how do you use these? Imagine that you get some text from a textarea in a HTML-form. This text is to be saved in a database so that you may generate a help-page, blog, guestbook or something similar later on. Before saving the text you pipe the text through both these filters just like:

tidy -config tidy.conf < html-file | html_scrub -f html_scrub.cfg

With the supplied configuration files the following text:

This <B>paragraph <I>has</B> nested</I> tags.

This paragraph has <B>two closing tags</I></I>.

This paragraph <B>has an open tag.


This <STRONG>paragraph <EM>has</EM> nested</STRONG> tags. This paragraph has <STRONG>two closing tags</STRONG>. This paragraph <STRONG>has an open tag.</STRONG>

Here is a quick 'n dirty example on how to call these filters from Perl. Remember that the buffering might mess things up for you so this is the reason to why I closed the writer before reading from the reader handle. It works fine for small inputs.

#!/usr/bin/perl -w

use strict;
use IPC::Open2;
use IO::Handle;

my ($reader, $writer) = (IO::Handle->new, IO::Handle->new);

open2($reader, $writer, "./tidy -config tidy.conf | ./html_scrub -f html_scrub.cfg");

print $writer <<EOT;
This <B>paragraph <I>has</B> nested</I> tags.

This paragraph has <B>two closing tags</I></I>.

This paragraph <B>has an open tag.

close $writer;

my $output = join("", <$reader>);
close $reader;

print $output;

The output is of course as above.

Some day I might write the "tag closer" anyway since tidy is rather large and does a lot more and might not do exactly just this. But we'll just have to wait and see.


©2003 Max Zomborszki
Updated 2004-06-17