#!/usr/bin/perl ################################################################# # G-Counter v2.0 # by Adam Watkins # http://www.watty.com # Distribute Freely ################################################################# ################################################################# # Version History: # v2.0 (5-02-01) # - Reworked the script with more error checking # - Completely reworked script # - Added format and inc option to query string # - Added Octal, Binary and Hexidecimal support # - Variable max digit support # - Added option to turn off on the fly counter adding # v1.6 (2-20-01) # -Change printing of the digits method to 1024 at a time # -Use a -e to see if count file exists first, if not create # -have it bomb out if if can't open count file ################################################################# # How to set up? # # Or if you don't support SSI of you don't want to use it there is another way! # Put the following lines into your page: # # # # # # # # #
# # How it works! In ?name&d&0&9 the values are name, format, inc, and digit. # name -> This is the counter name. This can allow you to run many # counters off this one script. It can be digits or text. # format -> This is the format the digits should be displayed in. # d = Decimal, b = binary, h = hexidecimal, o = octal # inc -> 1 - Increment count, 0 - do not increment count. # This is used for if you are displaying all the different # number formats on the same page, you don't increment all of # them (unless you want to). # *NOTE* If you display more than one count on a page make sure # the one that loads LAST is the one that increments # digit -> Which digit of the count to display. # # The ?name&d&0&0 spot is the first decimal digit in the number. You don't need to show all ?0&d&0&0 thru ?0&d&0&9 # If your count is only 55. All that you need to show is ?0&d&0&0 and ?0&d&0&1 # But, you can show them all. If you do, it will display 0000000055 # You can go as high up to the value in $diglimit below. # # Also note that the the only once set to increment is the 1st digit (0), so it only increments the counter once. (not 10 times) # The example shown above will show the counter called "name" in decimal format to 10 digits. # # ALSO NOTE: If you do not use my supplied images, you will need to change the height # and width also. # # chmod 777 the file & the directory, $basedir/$baseurl, specified below # Upload all your images to that directory too # Upload gcounter.pl and chmod 755 # # NOTE: If not using $onthefly counter generation mode (default yes, set below) then you must create counter files. # If the name of your counter is 'name' then create a file called gc_name.txt in the $basedit, # place a 1 in it (0 will error), and chmod 777 the file # # Then... edit these lines... ########################################## # This is where graphics and count files go $basedir = "../cgi-bin"; $baseurl = "http://www.lesliehouk.com/cgi-bin"; ########################################## # What kind of graphics files are you using? # if you are using gif uncommnet the gif lines and # comment the jpg lines. And visa versa. # Set Default to the type of the graphics included. $type = "image/gif"; $ext = ".gif"; #$type = "image/jpg"; #$ext = ".jpg"; ########################################## # What is the width and height of your graphics? # Set Default to the size of the graphics included. $imgwidth = "15"; $imgheight = "18"; ######################################### # Use file locking? (flock) # set equal to yes if your server supports it $lock = "no"; ######################################### # Make new counters on the Fly? # You can just put a new counter name and a # new counter file will be made for it. $onflynew = "yes"; ######################################### # Digit Limit # Shouldn't have to change this $diglimit = 16; ########################################## # NO Need to edit below here my $use_ssi = 1; #value to keep track if using ssi to display, default yes my $limit; #keeps track of how many characters are in the count my @numstf; #this is the count as an array with leading 0's my $file; #this is the file of the digit that non-ssi will display # go and get the count, puts it into @numstf, sets limit and file and use_ssi &get_cnt; # displays the count based on use_ssi, limit for ssi mode and file for non-ssi mode.. uses @numstf &prnt_cnt; ######################################### # Begin Subroutines sub get_query { my $command; #Query string my $counter_name; #counter name parsed from query string my $dig2display = ""; #digit 2 display (not using ssi) my $format; #number format to display (hex, bin, dec) my $inc; #whether or not to inc if ($ENV{'QUERY_STRING'} ne '') { $command = "$ENV{'QUERY_STRING'}"; } else { #must have command line info to operate error("No command line information"); } if ($command =~ /(.*)&(.*)&(.*)&(.*)/) { $counter_name = $1; $format = $2; $inc = $3; $dig2display = $4; } elsif ($command =~ /(.*)&(.*)&(.*)/) { $counter_name = $1; $format = $2; $inc = $3; } elsif ($command =~ /(.*)&(.*)/) { #legacy/shortcut support for non-ssi $counter_name = $1; $format = "d"; $dig2display = $2; if ($dig2display eq "0") { $inc = 1; } else { $inc = 0; } } else { #legacy/shortcut support for ssi $counter_name = $command; $format = "d"; $inc = 1; } #error checking the query string input error("format is illegal") unless ($format eq "b" or $format eq "h" or $format eq "d" or $format eq "o"); if (($dig2display) || ($dig2display eq "0")) { #mark the global variable that we are not using ssi $use_ssi = 0; error("digit to display is invalid") unless ($digit2display >=0 or $digit2display < $diglimit); } #return ($counter_name,$format,$inc,$dig2display); } sub get_cnt { my $numtemp; #value recieved from the counter file (cannot be 0) my $dispnum; #number in format to be displayed in (dec, bin, or hex) my @numarray; #turn the decimal number into a array of characters for shifting my $limcnt; #counter to do the character shifting based on the limit my $du; #each charater in the numarray my $i; #for loop variable #get values from the query string my ($counter_name,$format,$inc,$dig2display) = &get_query; #see if count file exists, if not try to create it if (!( -e "$basedir/gc_$counter_name\.txt")) { if ($onflynew eq "yes") { &new_file($counter_name); $numtemp = 1; } else { error("No counter file"); } } else { #get count open (CNT, "$basedir/gc_$counter_name\.txt") || error("could not get count"); $numtemp = ; close(CNT); #make sure we get a number error("no counter number") unless ($numtemp); } #to strip of excess $numtemp = int($numtemp); #if format is not decimal, convert it to another format if ($format ne "d") { ($dispnum) = num_convert($format,$numtemp); } else { $dispnum = $numtemp; } #checking for number of digits $limit = length($dispnum); $limit = $limit-1; #split into an array of digits @numarray = split(//, $dispnum); #initializing each to 0 for($i=0;$i<16;$i++){ $numstf[$i] = 0; } #filling the appropriate spots with digits $limcnt = $limit; foreach $du (@numarray) { $numstf[$limcnt] = $du; $limcnt--; } if ($inc) { increment_num($counter_name,$numtemp); } $file = "$basedir/$numstf[$dig2display]$ext"; } sub prnt_cnt { my $size; #size of the file to display in non ssi mode my $i; #for loop var if ($use_ssi) { print "Content-type: text/html\n\n"; print "\n"; for ($i=$limit;$i>=0;$i--){ print "\n"; } print "
\n"; } else { if ( open(IMGF, $file)) { $size = ( -s $file); print "Content-type: $type\n"; print "Content-length: $size\n\n"; while(read(IMGF,$data,1024)){ print $data; } close (IMGF); } } } sub new_file { my ($counter_name) = @_; open (NEWCNT, ">$basedir/gc_$counter_name\.txt") || error("Could not create the new file"); print NEWCNT "1"; close(NEWCNT); } sub increment_num { my ($counter_name, $numtemp) = @_; $numtemp++; open (CNT2, ">$basedir/gc_$counter_name\.txt"); if ($lock eq "yes") { flock CNT2, 2; } print CNT2 "$numtemp"; if ($lock eq "yes") { flock CNT2, 8; } close(CNT2); } sub error { ($error) = @_; print "Content-type: text/html\n\n"; print "ERROR: $error\n"; exit; } sub num_convert { my ($format, $numtemp) = @_; my $dectmp = $numtemp; my $convnum = ""; my $rmdr; #format is binary if ($format eq "b") { while ($dectmp != 0) { $rmdr = $dectmp - (int($dectmp / 2) * 2); $convnum = $rmdr . $convnum; $dectmp = int($dectmp / 2); } #format is hexidecimal } elsif ($format eq "h") { while ($dectmp != 0) { $rmdr = $dectmp - (int($dectmp / 16) * 16); if ($rmdr eq "10") { $rmdr = "a"; } elsif ($rmdr eq "11") { $rmdr = "b"; } elsif ($rmdr eq "12") { $rmdr = "c"; } elsif ($rmdr eq "13") { $rmdr = "d"; } elsif ($rmdr eq "14") { $rmdr = "e"; } elsif ($rmdr eq "15") { $rmdr = "f"; } $convnum = $rmdr . $convnum; $dectmp = int($dectmp / 16); } #format is octal } elsif ($format eq "o") { while ($dectmp != 0) { $rmdr = $dectmp - (int($dectmp / 8) * 8); $convnum = $rmdr . $convnum; $dectmp = int($dectmp / 8); } #format is something else, so how. should never happen } else { $convnum = $numtemp; } #return $convnum; }