#!/usr/local/bin/perl # Counter ############################## use NDBM_File ; use Fcntl ; use Fcntl ':flock'; open (CONFIG,"config.txt"); while () { chop $_ if ($_ =~ /\n/); @line=split(/=/,$_,2); $config{"$line[0]"}=$line[1]; } close (CONFIG); $minLen = 1; $isHigh = 1; $isInverse = 1; $lockWait = 5; $counterFile = $ENV{QUERY_STRING}; $counterFile =~ s/\//_/g; &initialize; # hit accesses are logged to the cntdb database by host, address, port key # and the last access time in secs from 1970 is stored per source address # only accept a new hit from an identical source if more than a day has passed # the total number of hits is stored under key "totalhits" $dbfname = "$config{'data_dir'}/counter/$counterFile"; # print "dbfname = $dbfname\n"; # obtain lock $lck = "$dbfname.lck"; $i = 0; until (sysopen(FH, $lck, O_RDWR|O_CREAT) && flock(FH, LOCK_EX|LOCK_NB) || $i++ > $lockWait) { sleep(1); } if ( $i > $lockWait ) { print "Content-type: text/plain\n\nCan't lock file $lck\n"; exit(1); } chmod 0666, "$dbfname.dir", "$dbfname.pag", "$dbfname.lck"; # open database tie(%h, 'NDBM_File', "$dbfname", O_RDWR|O_CREAT, 0666); $totalReads = $h{"totalhits"}; #print "totalReads = $totalReads\n"; if ($totalReads == "") { $totalReads = 0; } $key = "$hostname,$host,$port"; # print "key = $key\n"; $oldlv = $h{$key}; # previous time value, blank if no hit before # if no prior hit or last hit more than 24 hours ago update hit count and time if ( "$oldlv" == "" || ($oldlv + 86400 < time) ) { $totalReads++; $h{"totalhits"} = $totalReads; # increment hit count $h{$key} = time; # update hit source time to now } untie %h ; # release lock close FH or die "can't close lockfile: $!"; # print counter image &generateBitmap; &writeBitmap; exit(0); sub writeBitmap { print ("Content-type: image/x-xbitmap\n\n"); if ($isHigh) { printf ("#define count_width %d\n#define count_height 16\n", $len*8); } else { printf ("#define count_width %d\n#define count_height 10\n", $len*8); } printf STDOUT "static char count_bits[] = {\n"; for($i = 0; $i < ($#bytes + 1); $i++) { print("0x$bytes[$i]"); if ($i != $#bytes) { print(","); if (($i+1) % 7 == 0) { print("\n"); } } } print("};\n"); } sub generateBitmap { $count = $totalReads; @bytes = (); $len = length($count) > $minLen ? length($count) : $minLen; $formattedCount = sprintf("%0${len}d",$count); if ($isHigh) { for ($i = 0; $i < $len*3; $i++ ) { if ($isInverse) { push(@bytes,"ff"); # add three blank rows to each digit } else { push(@bytes,"00"); } } } for ($y=0; $y < 10; $y++) { for ($x=0; $x < $len; $x++) { $digit = substr($formattedCount,$x,1); if ($isInverse) { # $inv = 1 for inverted text $byte = substr(@invdigits[$digit],$y*3,2); } else { $byte = substr(@digits[$digit],$y*3,2); } push(@bytes,$byte); } } if ($isHigh) { for ($i = 0; $i < $len*3; $i++ ) { if ($isInverse) { push(@bytes,"ff"); # add three blank rows to each digit } else { push(@bytes,"00"); } } } } sub initialize { $hostname = $ENV{REMOTE_HOST}; $host = $ENV{REMOTE_ADDR}; $port = $ENV{SERVER_PORT}; # bitmap for each digit # Each digit is 8 pixels wide, 10 high # @invdigits are white on black, @digits black on white @invdigits = ("c3 99 99 99 99 99 99 99 99 c3", # 0 "cf c7 cf cf cf cf cf cf cf c7", # 1 "c3 99 9f 9f cf e7 f3 f9 f9 81", # 2 "c3 99 9f 9f c7 9f 9f 9f 99 c3", # 3 "cf cf c7 c7 cb cb cd 81 cf 87", # 4 "81 f9 f9 f9 c1 9f 9f 9f 99 c3", # 5 "c7 f3 f9 f9 c1 99 99 99 99 c3", # 6 "81 99 9f 9f cf cf e7 e7 f3 f3", # 7 "c3 99 99 99 c3 99 99 99 99 c3", # 8 "c3 99 99 99 99 83 9f 9f cf e3"); # 9 @digits = ("3c 66 66 66 66 66 66 66 66 3c", # 0 "30 38 30 30 30 30 30 30 30 30", # 1 "3c 66 60 60 30 18 0c 06 06 7e", # 2 "3c 66 60 60 38 60 60 60 66 3c", # 3 "30 30 38 38 34 34 32 7e 30 78", # 4 "7e 06 06 06 3e 60 60 60 66 3c", # 5 "38 0c 06 06 3e 66 66 66 66 3c", # 6 "7e 66 60 60 30 30 18 18 0c 0c", # 7 "3c 66 66 66 3c 66 66 66 66 3c", # 8 "3c 66 66 66 66 7c 60 60 30 1c"); # 9 }