#!/usr/bin/perl
# countfly.cgi - creates an inline PNG image for use as
# a graphical access counter. This script executes
# Martin Gleeson's fly as an external program (see below).
# Usage: <IMG SRC="http://www.global-dialog.org/mvdtestbed/countfly.cgi?access.txt">
# Copyright 1996 by Stephen Lines (spraxlo@ai.mit.edu)
# modified slightly by Gerry Smith (carve@telusplanet.net)

require "countf.pl";

############## CONFIGURATION VARIABLES ##############

$countFile   = $ENV{'QUERY_STRING'}; # File storing the count as its first line
$accessLog   = $countFile;   # File for logging accesses (same file)
$errorLog    = "errors.log"; # File for logging "errors" (may be same file)
$useLog      =  0;           # To turn off logging, change this to 0
$digitDir    = "/home/glblcore/public_html/graphics";       # Holds PNG images
$digitWidth  =  20;          # All digit images must be of equal width
$digitHeight =  32;          # Ditto their height
$frameSize   =  0;           # Extra space around the number, in pixels
$frameColor  = "0,0,0";      # RGB, so "255,255,0" is yellow, etc.
$flyProg     = "./fly";   # (Relative) path of the fly program
$otherImgURL = "";           # URL of image to send INSTEAD of count
$transColor  = "1,1,1";      # Set to "0,0,0" to make black transparent.
$interlace   =  1;           # Create counter image as interlaced.
$|           =  1;           # Unbuffer STDOUT before opening a pipe.

$date_command = '/bin/date';

# To prevent other Web pages or sites from using this counter, put only
# the trusted URL(s) or Web server(s) in $referers, separated by |'s.
# If you're counting hits to one page only, put in its whole URL.
$referers = 
"http://www.global-dialog.org|http://global-dialog.org|http://www.telusplanet.net/public/carve|http://www.kalitantra.net|http://mariposy.net|http://www.mariposy.net";

############## THE MAIN PROGRAM #####################
#open(STDERR,">>errors.log");

# &checkReferer if ($referers);    # Reject bad referers

$count = &countf($countFile);    # Get the new count

if ($otherImgURL) {              # Redirect to some constant image
  print "Location: $otherImgURL\n\n"
} else {                         # Send the MIME header for new image
  print "Content-type: image/png\n\n";
  &sendPngCount($count);         # Subroutine creates and sends image
}

&appendLog($accessLog);          # Log access (if useLog is true)

exit;                            # Outta here

########### GENERAL SUBROUTINES #####################

sub appendLog {
  if ($useLog ) {
    local ($logFile, $message) = @_;
    #local ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
    #local  $date = sprintf("%02d.%02d.%02d %02d:%02d:%02d", $year, $mon, $mday,  $hour, $min, $sec);

    $date = `$date_command +"%A, %B %d, %Y at %T (%Z)"`; chop($date);

    open( LOG,">>$logFile") || die("$0: error opening logfile $logFile: $!");
    flock(LOG, 2);               # Get exclusive lock on the log file
    print LOG "$date $ENV{'HTTP_REFERER'} from ";
    print LOG "$ENV{'REMOTE_ADDR'} using $ENV{'HTTP_USER_AGENT'}";
    print LOG $message if $message;
    print LOG "\n";
    flock(LOG, 8);               # Release the lock
    close(LOG);
  }
}

sub checkReferer {
  unless ($ENV{'HTTP_REFERER'} =~ /$referers/) {
    appendLog($errorLog, " - bad referer");
    die("$0: bad referer $ENV{'HTTP_REFERER'} from $ENV{'REMOTE_ADDR'}\n");
  }
}

########## GRAPHICS SUBROUTINES #####################

sub sendPngCount {
  local  ($count) = @_;
  local   @digits = split(//, $count);  # Split string into array of chars

  # Compute width & height of output image:
  $imgWidth  = $digitWidth * @digits  +  ($frameSize * 2) + 14;
  $imgHeight = $digitHeight           +  ($frameSize * 2);

  # Open a pipe to send commands to the fly program (-q for quiet):
  # NB: flyProg will write to STDOUT, which should be flushed (set $| = 1):
  open( FLY,"|$flyProg -q") || die("$0: error opening pipe to $flyProg: $!");
  print FLY "new\n";
  print FLY "size $imgWidth,$imgHeight\n";
  print FLY "type png\n";
  print FLY "rect 0,0,$imgWidth,$imgHeight,$frameColor\n" if $frameSize;

  # Commands to copy individual digit images into the frame:

  $insertX = $insertY = $frameSize;
  print FLY "copy $insertX,$insertY,-1,-1,-1,-1,$digitDir/ltb.png\n";
  $insertX = $insertX + 6;
  foreach $digit (@digits) {
    print FLY "copy $insertX,$insertY,-1,-1,-1,-1,$digitDir/$digit.png\n";
    $insertX = $insertX + $digitWidth;
  }
  print FLY "copy $insertX,$insertY,-1,-1,-1,-1,$digitDir/rtb.png\n";

  print FLY "transparent $transColor\n" if ($transColor =~ /\d+,\d+,\d+/);
  print FLY "interlace\n"               if  $interlace;
  close(FLY);                           # Ahem...  Thanks for closing it.
}

######################### NOTES #####################
# Fly was written by Martin Gleeson for Unix; his online documentation
# (http://www.unimelb.edu.au/fly/fly.html) says:
# All x,y values are in pixels measured from the top left of the image.
# For a 128x256 image, top left is 0,0 and bottom right is 127,255.
# All x1,y1,x2,y2 pairs must specify the top left and bottom right of the
# shape, where appropriate. (And -1 means min or max possible value.)
				
				
				
				
				
				
				
