Demo for Luhn algorithm in PHP

If you have a number that adheres to the Luhn algorithm for validation, you may check it easily with this short PHP snippet.

function luhn($str) {
        $odd = !strlen($str)%2;
        $sum = 0;
        for($i=0;$i<strlen($str);++$i) {
            if($odd) {
            } else {
$num = $_GET['number'];
<title>Online Luhn algorithm test</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<?php if($num) { ?>
<?php   if(luhn($num)) { ?>
<div style="background:#ddffdd;border:1px solid #004400;">
<?=htmlspecialchars($num)?> is valid
<?php   } else { ?>
<div style="background:#ffdddd;border:1px solid #880000;">
<?=htmlspecialchars($num)?> is NOT valid
<?php   } ?>
<?php } ?>
<form action="luhn.php" method="GET">
Number: <input type="text" name="number" value="<?=urlencode($num)?>" size="40"/>
<input type="button" name="btSend" value="Check"/>

You may test this script at
Please consider that this is a demo, so please do not use this to check credit card numbers unless you send me an expiry date. CCV2 has taken over as the preferred method for credit card number validation anyway.

Find out LDAP client IPs is a simple perl filter that processes SunONE Directory Server 5.2 access logs to find out the IP addresses that queries are coming from. It’s very useful to evaluate the impact for migrating LDAP infrastructures. Most comments and variable names are in spanish but the code should be clear enough to any SODS sysadmin. Or drop me a line if you absolutely need an all-english version.

# $Revision: 1.1 $
# Analiza archivos access de Sun ONE Directory Server 5.2 para generar
# reporte de IPs de clientes y servidores
# Copyright (C) 2005 Javier Arturo Rodriguez
use strict;
my $filename = shift @ARGV;
die("Usage:\t$0 <filename>\n\tbunzip2 -c <filename.bz2> | $0 -\n") unless $file
while(<FILE>) {
        if($_=~m,^\[(.*?)\].*?connection from ([\d\.]+) to ([\d\.]+),) {
foreach my $dst (sort keys %{$acceso||{}}) {
        print "Acceden a traves de $dst\n";
        foreach my $src (
                reverse sort { $acceso->{$dst}->{$a}->{CNT} <=> $acceso->{$dst}
->{$b}->{CNT} }
                keys %{$acceso->{$dst}||{}}
        ) {
                printf("  %-15s (last seen on %s; %d hit%s)\n",


Get stock quotes into a spreadsheet

This code stnippet grabs a .CSV file from Yahoo! Finance with selected quotes. This is very useful to keep an eye in your portfolio from within Calc, Gnumeric, Kspread,Microsoft Excel or similar program using your very own models.
To use it edit the paths and the symbols in the script, run it periodically from cron(8) to get $DEST/quotes.csv, import the file once and reference it from your own spreadsheet.

echo '"SYMBOL","VALUE","A","B","C","D","E","F","G","H"' > $DEST/quotes.csv
cat $TMP/quotes.csv >> $DEST/quotes.csv

Mitigate the .WMF vulnerability with Exim, Squid and SquidGuard

Unless you’ve been on holiday leave you’ve probably heard about the WMF vulnerability by now. Everything seems to indicate that Microsoft won’t take action to patch this gaping hole before January 9th, so here are a few measures to be on the safe side.

1. Before you do anything else, go ahead an unregister SHIMGVW.DLL

C:\> regsvr32 -u %windir%\system32\shimgvw.dll

Put this in a login script, and just for good measure go ahead an run it in every Windows box you’re responsible for. Heck, run it even in those you’re *not* responsible for as well.

2. I already got quite a few .WMF attachments on the spamtraps. F-Secure has a very interesting specimen and a lot to say about it. So the next step is to block them in exim.conf. Enable the acl_check_content ACL and make sure that you have a rule like this one:

  deny  message = This message contains an unwanted file extension ($found_extension)
        demime = scr:vb:vbs:vbe:js:jse:reg:bat:lnk:pif:hlp:dll:com:rar:wmf

3. SquidGuard can filter URLs that match a given regular expression. Add these regexes to a local-blocks/expressions or similar file:


Note that the .dll and .js extensions aren’t blocked for HTTP. That’s because the lovely IIS uses the .dll suffix for its extensions, and you can’t block JavaScript for HTTP either unless you want to break 90% of the Internet for all your local clients. I firmly belive that blocking them for FTP is just fine, tough.
Update 20060102 125530: Jeremy Gaddis shares a squid recipe.

Of course, this only applies if you use exim and Squid+SquidGuard -which by the way are all excellent Open Source products- but the same principle applies to any other mail and proxy servers. If you implement all three recommendations you should be fine. User should not get .WMF files through email or the Web. Even if a clueless user catches it though some other means (IM, external e-mail account, a *ack!* floppy disk/CD-ROM/flash drive, a helpful colleage, etc.) the REGSVR32 workaround should keep the exploit at bay. If you definitely need to work with WMFs, there are other alternatives as outlined by Richard Bejtlich. Just don’t hold your breath for a Microsoft-backed patch.

<rant>And about Microsoft’s “swift” response to this issue: The next time that someone gives me the line about not using Open Source because there’s nobody to take responsibility for problems, I’ll puch him in the face without further warning.</rant>


This small script is an alternative to sleep(1) that gives a visual clue to the user about the remaining seconds in the delay


my $secs = shift;
die("Usage: $0 <secs>\n") unless (defined $secs) && ($secs>=0);
while($secs>0) {
        printf("\r% 4d", $secs);
        sleep 1;
print "Done          \n";

There are numerous instances where you might want your shell scripts to sleep(1) giving the user a clue about what’s going on, but just to relate to a previous example, let’s see how this can be used to throttle file leeching:

$ for i in `count 1 10 %02d`; do wget http://..../file-$i.pdf; countdown 30; done

Anansi Boys

Anansi BoysIt took a bit longer than I originally expected, but last night I finally finished reading Anansi Boys and I just have this to say: Neil Gaiman is a master storyteller.
Neil has just weaved a great story from a few seemingly loose strands in American Gods and -I swear- it is a solid web that he traps the reader into. The characters are solid and well developed over time, and by the end of the book they jump right off the page. The situations are very well constructed and some scenes have a frail, dreamlike quality. I can certainly relate to some aspects of the situations that Fat Charlie goes through, most certainly to those bits about parents being involuntarily embarrasing entities. As it is written, the characters’ ultimate destinies are very much like melodies that intertwine gradually and evolve into a great, powerful song. This song flows naturally, armonically, unavoidably. The musical bridges are in their right place, and in retrospect I can see that every note is there for a reason. The end resonates loudly, like a sustained note in a song I that I feel that I’ve heard before. And I probably have: Even now, Neil is one of the few authors that has the strange gift of haunting my sleep with their stories.
Neil: while you’re conceivably baking in the sun and healing from that nasty cold in some heavenly island in the Caribbean after which you shaped St. Andrews, I just have to thank you for taking me wide awake to that mysterious land at the beginning of time that we ordinary humans only visit in our sleep.


count is a minimalist perl script in the spirit of seq(1) but with a simpler syntax. It only counts in increments of 1, but -on the other hand- it knows how to count down.

use strict;
print join("\n",map{sprintf("$fmt",$_)}($from>$to?reverse($to..$from):($from..$to))),"\n";

For instance, “count 10 1 %03d” will count down from 10 to 0 padding with zeroes to three digits. “count 0 15 %x” will count in hex. If you omit the format string it will default to “%d” (decimal, no padding).
count is very useful -among other things- for file leeching:

$ for i in `count 1 10 %02d`; do wget http://..../file-$i.pdf; done


Base64 is used to encode binary data in printable ASCII form. de64 is a trivial perl script to decode such strings:

use MIME::Base64;
local $/ = undef;
print decode_base64(shift||<STDIN>);

One application of de64 is decoding UTF8 LDAP attributes inside LDIF files. For instance, “cn:: Um9iZXJ0byBNYXJ0w61uZXo=” may be decoded with

$ de64 Um9iZXJ0byBNYXJ0w61uZXo=
Roberto Martí­nez

(Look Randal! I’m using a CPAN module this time! ;-) ) Of course, all the heavy lifting is done by MIME::Base64 from CPAN.