Home Articles FAQs XREF Games Software Instant Books BBS About FOLDOC RFCs Feedback Sitemap
irt.Org

Related items

CGI Security : Better Safe than Sorry

Speed Thrills : CGI Please ... and Fast!

CGI Programming Made (Relatively) Easy Using Libraries

Server-Side Includes and its Extensions

Random and Recursive Crypting using Salt on Unix and Win32

Timestamping an HTML Document

Deleting Files in Perl

Creating a mailing list using Perl

Reading and Writing to Files on the Server

Server Side Includes and CGI Security

Creating a Page Counter In Perl

You are here: irt.org | Articles | CGI & Perl | Creating a Page Counter In Perl [ previous next ]

Published on: Sunday 18th July 1999 By: Jason Nugent

Introduction

Well, I know I've been gone for a while, but that's because Real Life got extremely busy all of a sudden. At any rate, I'm back with a new Perl article. I've decided to write an article on this topic because it seems that fully 80% of all the questions I've received as of late have been about this topic. Without further ado, here goes.

My rant about Counters

Generally, page counters don't really offer a webmaster any useful information that they cannot get through some other means. You *do* have your server logs, and they contain more information that could possibly be represented by a single number on the bottom of your page. Counters are pretty much only good for vanity, and please, don't use them if you only get 5 hits a week. Not worth it.

Anyway - on to the Counter

This article describes a counter that is going to be run as a Server Side Include. Essentially that means that we are going to write a Perl script that will run each time the page is loaded and its outputted HTML will contain a line of text indicating how many people have seen the page. It sounds pretty simple, and it is. Let's get started.

Counter.pl - the Good Stuff

As always, the first line in your Perl script must be a locator line pointing to the location of the Perl interpreter installed on your server.

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

Remember, we add the -w to turn on extra warning information to help us debug our script.

Essentially, this script is going to open a text file on the server, read something from it (the number of visitors prior to this visit), increment a number, and print something to STOUT. To read a file, we use the following syntax:

$file = 'file location goes here';  # must be readable/writable by your webserver's user
open (FILE, "+>>" . $file) or die "cannot open $file for reading and appending: $!";
flock(FILE, 2) or die "cannot lock $file exclusively: $!";

The above code also makes a few concessions we've discussed in previous articles. It opens the file in read/append mode so we can read the contents in and still overwrite it, and it locks the file in case something else tries to access it before we have completely finished with it. We also call 'die' to ensure that if something goes wrong, our script doesn't continue to run and cause problems.

Once we have our file opened, we must move to the beginning of the file so we can read in the file's contents (since opening it in append mode automatically puts the pointer at the end of the file). We do this in the following manner:

seek FILE, 0, 0;

and then we read the file's contents into an array.

my @file_contents = <FILE>;  # we use an array even though there won't be more than a single line of data here.

Now that we have the files contents, we can truncate the file to zero size so we can overwrite it once we know what the new counter amount will be. We do this using the 'truncate' command:

truncate FILE, 0;

Essentially, all we have to do now is extract our number out of our array and increment it. I will use a regular expression for this, even though you could quite conceivably do it by simply grabbing the first element of the array without checking since there most likely won't be anything but a number here. Using a regular expression gives you the opportunity to do some error checking, which makes it a nice way to go about it.

my $counterVar;

if ($file_contents[0] =~ /^(\d+)$/)
{
   $counterVar = $1;  # $1 is captured by the ()'s in the regular expression
}
else
{
   $counterVar = 'COUNTER ERROR';  # the regular expression didn't match
}

For the rest of the article, we'll assume that the regular expression matched. Normally, you would check to see if it did or not, and perform appropriate error handling at that point.

Now that we have our counter value, we can increment it, store it in our file, and print it to the browser:

$counterVar++;  # auto-increment the same variable with 1

To store it in the file, we just print to the filehandle and close our file.

print FILE $counterVar;  
close (FILE);

print STDOUT "Content-type: text/html\n\n";  # this line is always needed!
print STDOUT "<STRONG>You are the " . $counterVar . "th visitor to this page.  Welcome!</STRONG><BR>" . "\n";

To get this to work, all you need to do is insert an exec Server Side Include in your page and make sure you have SSI enabled in your webserver. There are ways to get around using SSIs that are better alternatives, but I'm not going to get into them just yet. Maybe in a future article ;)

Something like this works just fine:

<!--#exec cgi="/cgi-bin/counter.pl" -->

Where /cgi-bin/counter.pl is the actual path to your counter perl script. Note, that you NEED the "exec" SSI enabled. Most webservers that have SSI enabled probably have this one turned off, since it is a security risk. If you have questions about that, talk to your sys admin.

The Complete Code

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

$file = 'your file location goes here';  # must be readable/writable by your webserver's user
open (FILE, "+>>" . $file) or die "cannot open $file for reading and appending: $!";
flock(FILE, 2) or die "cannot lock $file exclusively: $!";

seek FILE, 0, 0;

my @file_contents = <FILE>;

truncate FILE, 0;

my $counterVar;

if ($file_contents[0] =~ /^(\d+)$/)
{
   $counterVar = $1;  # $1 is captured by the ()'s in the regular expression
}
else
{
   $counterVar = 'COUNTER ERROR';  # the regular expression didn't match
}

$counterVar++;  # auto-increment the same variable with 1
                # note: with this code, if counterVar is NOT an incrementable number, $counterVar will be set to 1.
                # that's not necessarily a bad thing.

print FILE $counterVar;
close (FILE);

print STDOUT "Content-type: text/html\n\n";  # this line is always needed!
print STDOUT "<STRONG>You are the " . $counterVar . "th visitor to this page. Welcome!</STRONG><BR>" . "\n";

end(0);

Related items

CGI Security : Better Safe than Sorry

Speed Thrills : CGI Please ... and Fast!

CGI Programming Made (Relatively) Easy Using Libraries

Server-Side Includes and its Extensions

Random and Recursive Crypting using Salt on Unix and Win32

Timestamping an HTML Document

Deleting Files in Perl

Creating a mailing list using Perl

Reading and Writing to Files on the Server

Server Side Includes and CGI Security

Feedback on 'Creating a Page Counter In Perl'

©2018 Martin Webb