WWW Homepage Access Counter!

[Count Release 1.5]

Latest Release: September 17, 1995
Initial Release: April 13, 1995


Accesses to this page since April 13, 1995:

Announcement

Count 2.0 will be released this weekend. It will have resonable defaults for all parameters. Therefore, QUERY_STRING can become significantly short.

Release 2.0 won't happen this weekend, I'm too busy, sorry!

Features of Count 2.0

(Expected release date: October 22, 1995)

Note: all the coding of release 2.0 is done by Kevin J. Walsh. Please do not bother him with any questions regaring the counter.

October 10, 1995

Table of Contents

Requirements

Introduction

This is a CGI program to keep record of the raw hits of a web page. It generates a GIF image of the number of hits and returns to the browser as an in-lined image. The program also has run-time option not to show the digit images, this way the hits can be kept without displaying it. Almost all of the features are run-time options. The hits are no way accurate. Someone can reload the page again and again to increase the hits. However, people like to see how many times someone visited their page. This program started as a fun to play with CGI programming but due to enormous interest, and feature request, it has turned in to the most configurable counter on the web.

The program is distributed as a gzip'd tar archive. If you do not have gzip/gunzip, it's available at: prep.ai.mit.edu.

Features

Digit Styles

The digits used in this program are individual GIF files. This gives flexibility of using digits of your choice. The digit images are named as zero.gif, one.gif,.... nine.gif. At run-time, simply the directory of the images and width and height can be specified to use a different style. Therefore, a single program can generate digits of various styles. Here are the supplied digit styles.

Style A:

Style B:

Style C:

Style D:

The digits of style A and D are made by me, located at digits/A and digits/D directory of the source distribution respectively.

The digits of style B are borrowed from HTML-access counter. The digits are at the directory digits/B of the source distribution.

The digits of Style C are contributed by benjamin@pop3.oro.net. They are at the directory digits/C of the source distribution.

For a huge collection of GIF digits, check out the Digit Mania page.


If you like to share some cool digits with others, let me know, I'll put a pointer here. Please do not send me your digits.

Obtaing source archive

The source code for this program is distributed via the Web as a gzip compressed tar archive. If you do not have gzip/gunzip, it's available at: prep.ai.mit.edu.

This machine is getting enormous number of ftp requests lately. Therefore, I had to impose a limit of maximum 10 ftp connections at one time. The limit will go up to 50 maximum connections at 11:00 PM US Easern Statndard Time and go back to 10 maximum connections at 6:00 AM US Eastern Standard Time.

Sorry for the inconvenience!

current local time is: *
*:**

You can look at the log of the latest 10 ftp sessions.

For your information, here's the file transfer statistics from Septermber 15 till today.

Download source archive

The file wwwcount1.5.tar.gz is a gzip'ed tar file. To extract the distribution, at the shell prompt, type:
    gunzip < wwwcount1.5.tar.gz | tar xvf -
    cd wwwcount1.5
The program will compile with ANSI or non-ANSI C compiler.

Steps to compile

Edit config.h

  1. Edit the header file config.h, You have to change the directives ConfigDir, ConfigFile, DigitDir, DataDir, LogDir and LogFile.

    Note that the directives ConfigDir, DigitDir, DataDir and LogDir must define 4 separate directories, that is any of them can NOT have the same directory. Ok, this is what you need to do, first decide where you want to keep Counter related things. Let say, you want to keep Counter related things to the directory /usr/local/etc/Counter. If this directory does not exist, create it first, and then create 4 separate directories inside it, for example:

        mkdir /usr/local/etc/Counter
        cd /usr/local/etc/Counter
        mkdir conf
        mkdir digits
        mkdir data
        mkdir logs
    

    ConfigDir

    This directive defines the base directory of the configuration file. By default it is defined as:
    #define ConfigDir   "/usr/local/etc/Counter/conf"
    
    ConfigFile

    This variable defines the name of the run time configuration file for the counter program. The format of the file is discussed later. By default it is defined as:
    #define ConfigFile "count.conf"
    

    DigitDir

    This directive defines the base directory where the sub-directories of the digits are located. Please note carefully this directory does not contain the digit GIF images, it contains the sub-directories which contain the GIF images. For example, I keep the directories A, B, C, inside the directory /usr/local/etc/Counter/digits. The sub-directory A contains my led digits, B contains the odometer digits and C contains the chalk digits. The directories A, B and C reside inside the directory digits with the source distribution. By default this directive is:
    #define DigitDir "/usr/local/etc/Counter/digits"
    

    Make sure that this directory is searchable by the User defined in httpd.conf or by the Group defined in httpd.conf.

    DataDir

    This variable defines the base directory of the counter datafile. That means all the counter datafiles must locate in this directory. By default, this directive is:
    #define DataDir "/usr/local/etc/Counter/data"
    

    LogDir

    This directive defines the base directory of the counter log file. By default, this directive is:
    #define LogDir "/usr/local/etc/Counter/logs"
    

    LogFile

    This directive defines the name of the Counter error message and normal log file. Make sure the httpd has write permission to the base directory of this file, otherwise log will not be written to this file, instead it will be written to stderr. By default it is:
    #define LogFile "Count15.log"
    

Edit Makefile

  1. Now you need to look at the Makefile located at the base and the combine directory. By default CC is gcc, change it to cc if you need. The program can be compiled with the following flags:

    -DACCESS_AUTH

    If you want to stop "Counter Terrorism", you must add this flag to CFLAGS. It is defined by default. If the web browser supplies the environment variable HTTP_REFERER, the remote referer host will be extracted and compared with your host. If it differs, the request will be denied to serve the counter. If the browser does not supply the env variable HTTP_REFERER, counter will be served anyway. If you add this flag, you must add a new block to the configuration file. Look at the section Create configuration file for detail description of this block. Note, if you compile with this option, the above mentioned block must be present in the configuration file. I suggest you compile with this option.

    -DUSE_LOCK

    If you want datafile locking facility, you must add this flag to CFLAGS. This is added by default. Please note: if you are on a SYSV machine and you add this option, you must also add -DSYSV option to CFLAGS. This is an important feature, try to use this. This feature ensures that datafile will not get squashed by simultaneous access by hundreds of requests.

    -DALLOW_FILE_CREATION

    If you do not want to create data file for user, add this option to CFLAGS. If you compile with that flag, data file will be created if it does not exist and the value defined in run-time with st will be written to the data file. Make sure that the data directory has write permission to httpd. This option is very convenient. You do not have to create the data file for the user. But the dark side of this is anyone will be able to create datafile in the data directory. I do not suggest compiling with this option. It's here because many people requested for it.

Compile

at the shell prompt, type:
       make clean
       make

If compilation succeeds, it will create a binary Count.cgi. Now the program is ready to be installed. But before installing you have to create the configuration file you defined with ConfigFile to the directory you specified by ConfigDir.

Create configuration file

The configuration file controls some aspects of the counter program. The name of the file is defined with ConfigFile, and the location of this file is defined with ConfigDir in the config.h.

If any line starts with #, anything after the character is considered a comment and ignored. For Count 1.5, there are two blocks, the first one is the required block, that is it must exist, the other is optional block. The required block defines the IP addresses of the hosts to ignore from counting (e.g. your own host) and the optional block is the access authentication block. This is block is not needed if compiled without -DACCESS_AUTH option. if compiled with -DACCESS_AUTH this block also becomes a required block.

A block starts with { and ends with } in two separate lines. Note however, that this file can not have any empty line anywhere outside the blocks. If any empty line exists in this file, the program will act crazy. Therefore,

{
}
is a valid block. The beginning block defines the IP address of the hosts to ignore from counting. Example,
{
192.160.166.90
192.160.166.92
}
Each IP address has to be in a separate line and the maximum number of 100 hosts can be ignored. If you want to change it, edit the variable MaxSites in count.h. If you do not want to ignore any machine, just keep the block empty, like:
{
}
Wildcard can be used to ignore a entire domain, if the IP address starts with a number >= 192 and <= 223, the network is Class C, to ignore the entire domain of class C, put a * at the 4th octet like, 192.134.144.*

If the IP address starts with a number >= 128 and <= 191, the network class is B, to ignore the entire domain of class B, put a * at the 3rd octet like, 128.116.* or 128.116.*.*

If the IP address starts with a number < 128, the network class is A, to ignore the entire domain of class A, put a * at the 2nd octet like, 20.* or 20.*.*.*

You can use the full IP address for a specific host ofcourse, but if wildcard exist for this domain, it will take precedence.

However you CAN NOT omit this block. The left and right braces must present at two separate lines if you want to keep the block empty.

The second block is called Authentication block. This block must exist if compiled with -DACCESS_AUTH option. Each line contain hostname/IP address of the host who can access the counter. In my configuration file, this block looks like this:

{
    warm.semcor.com
    www.semcor.com
    warm
    www
    192.160.166.1
}
Here, warm.semcor.com is the machine I run the httpd server. I also have an alias defined for it, which is www.semcor.com. It also can be accessed locally by warm or www. The machine can be addressed with it's IP address as well. Replace them with your host. If you do not have any alias defined, just remove the line with www.semcor.com. Here, you also can give remote access to any hosts you like, just add another line with the host name.

For example, look at the supplied count.conf file. A Complete configuration file might look like this:

#############################################
# sample configuration file for Count 1.5
# by muquit@semcor.com
# 09/13/95, 9:15 PM
##############################################
#
# Note: NO EMPTY LINE IS ALLOWED IN THIS FILE
#
##############################################
# Ignore hosts block, you might want to ignore the local sites.
# THIS IS A REQUIRED BLOCK. If you do not want to ignore any hosts from
# counting, just put { on one line and } on the next line but make sure
# the braces exist!
######
#
# wildcard can be used to ignore a entire domain, if the IP address starts
# with a number >= 192 and <= 223, the network is Class C, to ignore the
# entire domain of class C, put a * at the 4th octet like,
# 192.134.144.*
# if the IP address starts with a number >= 128 and <= 191, the network class
# is B, to ignore the entire domain of class B, put a * at the 3rd octet like,
# 128.116.* or 128.116.*.*
# if  the IP address starts with a number < 128, the network class is A
# to ignore the entire domain of class A, put a * at the 2nd octet like,
# 20.* or 20.*.*.*
#
# you can use the full IP address for a specific host ofcourse, but if
# wildcard exist for this domain, it will take precedence
#
{
}
####
# Access authentication aka "Counter Terrorism" handling block
# This block must be present if you compile with -DACCESS_AUTH option
# If you do not compile with -DACCESS_AUTH, this block will not be
# read
# Each line contain the hostname/IP address of the host who can access the
# counter remotely. Yout hostname must be here.
###
{
    warm.semcor.com
    warm
    www.semcor.com
    www
    192.160.166.1
    charlie
}

Test the program from command line

A shell script is supplied for testing the counter. the name of this script is testcount.sh. Look at this script, you might need to change certain things. Please read the comments in this script for understanding the various run-time options of the counter. You'll also know in detail about the options in the section How to call the program.When you are happy with everything, save it and at the shell prompt type:
    testcount.sh

Install

The program Count.cgi is needed to be copied in a location designated by your server administrator as an appropriate location for CGI programs. The correct location of CGI programs vary from one serve to another. Ask your system administrator for the right location. Usually the location is /usr/local/etc/httpd/cgi-bin and you refer to the program as /cgi-bin/cgi_program.

Copy the configuration file (you defined with ConfigFile)to the directory (you defined with ConfigDir). Make sure that the directory is accesible and the configuration file is readable by httpd.

Copy the digit directories A, B, C, D etc. to the directory you defined with DigitDir

If you already didn't create the data directory (you defined with DataDir make the directory to the correct place.

If you didn't create the log file directory (you defined with LogDir), create the directory as well. You do not have to create the log file, it will be created if needed, only make sure that the log file directory has write permission to httpd.

How to call the program?

Let me tell you first, do not get frustrated because it has lots of options. I'll explain each option step by step. If you keep reading, you'll see it's really simple. You can refer to the program like this:

<img src="/cgi-bin/Count.cgi?ft=9|frgb=69;139;50|tr=0|trgb=0;0;0|wxh=15;20|md=6|dd=A|st=5|sh=1|df=count.dat" align=absmiddle>

The string between ? and " is called the QUERY_STRING. Make sure there is no newlines in the <img src= line and no space in the QUERY_STRING. Here:
    ft=9
       ft means frame thickness. If you want to wrap the counter
       with a ornamental frame, you define the frame thickness 
       like this. Here 9 is the thickness of the frame in pixel.
       This value can be any positive number more than 1. For nice
       3D effect, use a number more than 5. If you do not want
       frame, just use ft=0.
    
    frgb=69;139;50
       frgb defines the color of the frame. Here 69 is the red 
       component, 139 is the green component and 50 is the blue
       component of the color. The valid range of each component
       is >=0 and <= 255. The components must be separated by ;
       character. Note even if you define ft=0, these components
       must be present, just use 0;0;0 in that case.
    
    tr=0
       tr defines if you want transparency in the counter image.
       here tr=0, that is I do not want transparent image. If you
       want transparent image, define tr=1. Note that Coun.cgi, 
       does not care if your digits are transparent GIFs or not.
       You must tell explicitly which color you want to make 
       transparent.

    trgb=0;0;0
       if tr=1, then black color of the image will get transparent.
       Here 0;0;0 are the red, green and blue component of the color
       you want to make transparent.
    
    wxh=15;20
       wxh string defines the width and height of an individual 
       digit image. Each digits must have the same width and 
       height. If you like to use digits not supplied with my
       distribution, find out the width and height of the digits
       and specify them here.

    md=6
       md defines the maximum number of digits to display. It can be
       >= 5 and <= 10. If your counter number is less than md, the
       left digits will be padded with zeros. Here md=6 means, display
       the counter with maximum 6 digits. f you do not want
       to left pad with zeros, use pad=0 instead of md=6.
       Note you can either use md=some_number of pad=0, in this
       field, you can not use both. If you use pad=0, then
       the digits will be displayed exactly without padding.
        
    dd=A
       dd means digit directory. A indicates, it will use my LED digits
       located at the directory A. The base of the directory A is defined
       with DigitDir at step 1.

    st=5
       st means start, that is start the counter with this value. st is
       only significant if you compiled the program with 
       -DALLOW_FILE_CREATION. If you compiled with this option, the
       datafile will be created to the directory defined byDataDir
       in the config.h file and 5 will be written to it. This
       option is new in this release.
       
    sh=1
       sh mean show. If sh=0, then no digit images will be displayed,
       however a transparent 1x1 transparent GIF image will be
       returned, which will give the illusion of nothing being displayed.
       Althouh it will seem that nothing is displayed, the counter will
       be incremented all right. This option is new in this
       release.

    df=count.dat
       finally df means data file. This is the file which will contain the
       counter number. The base directory of this file is defined 
       with DataDir in config.h file. If you did not compile with the
       flag -DALLOW_FILE_CREATION, this file must exist. To create this
       file, at the shell prompt do this:

            echo 1 > count.dat
       
       or use a editor to create it.  If you compiled with the flag
       -DALLOW_FILE_CREATION, the file will be created and the value
       defined by st will be written to it. Make sure that the directory has
       write permission to httpd.
All these options must be in the same order as told and all in lower case and all of them must exist. Anyway, look at this Example Page, you will get the picture.

What is "Counter Terrorism"? And how this program handles it?

If you do not know, in most cases any CGI program can be referred remotely. For example, a CGI program x.cgi (say it returns an in-lined image) in foo.com can be called from foobar.com as follows:
    <img src="http://foo.com/cgi-bin/x.cgi">
That is, someone somewhere on the Internet can refer to your counter and increase the hits and you will not have a clue. You will get the false impression of many people visiting your page. You can look at the so called "Counter Terrorist" page for demo.

So how this program handles this? It handles it in two ways, first if you compile with -DACCES_AUTH flag, it will try to get a environment variable called HTTP_REFERER for remote referer. It is necessary to check this variable because when someone remotely refer to a CGI program to your machine, the variable REMOTE_ADDR will be the address of your machine. So checking REMOTE_ADDR will not work. Most of the moderm browsers returns the env variable HTTP_REFERER. If the browser does not return the variable, counter will be served anyway. But you are not lost totally here. If you decided to ignore count for your host running httpd, the counter will be served but it will not be increased. So, I suggest ignore count for your host and also compile with authentication feature.

Error Messages

Count will try to return an image in any event. That is, even if it fails for some reason, it will write the error messages in GIF format. The text error messages also will be written to the counter log file defined with LogFile in the directory defined with LogDir in the config.h file.

If you see any of these images, please check the Counter log file you defined with LogDir and LogFile. If the program could not create the log file, it will write the error messages to stderr. In that case if you configured your httpd server to write the log to a file, the error messages will the written to this file.

Frequently Asked Questions

  1. My CGI scripts don't work. What's wrong?

  2. How can I change the color of the digits?

    Change directory to the directory where GIF images of digits zero through nine are kept. Then use display program comes with ImageMagick to edit the color. type:

          display *.gif
           click middle mouse button on image for magnification window
           click left mouse button on image for command window
          Image Edit->Color
          Pixel Color->
          Method->replace
           place cursor anywhere on green area and click left mouse button
          Dismiss
          File->Save
          Save
            for next digit, press right mouse button image and select Next or
            press n. Change color the same way
    
    Or use the program mogrify comes with ImageMagick. mogrify can change a specific color of all the images at one shot. For example, if you want to change the green color to white, do this:
        mogrify -pen white -opaque green *.gif
    

Copyright

Copyright 1995 by Muhammad A Muquit. Permission to use, copy and modify this program for personal use is hereby granted without fee, provided that the program is not used for any financial gain and this copyright notice appear in all copies and both that copyright notice and this permission notice appear in supporting documentation. If the progam is ported to some other platform, no binary only distribution is allowed, the source and this copyright notice must be included with the distribution. This program is provided "as is" without express or implied warranty. Note: This program is developed in my own time. My employer SEMCOR, Inc. has nothing to do with it.

Acknowledgment

Thanks to John Cristy for ImageMagick. I took many routines from ImageMagick for the GIF image combining library. I borrowed the font array and some code from gd library. Thanks to Tom Boutell. Thanks to all of you who showed interest in the counter program. I had fun writing it.

I like to hear from you

If you are using this program, I like to hear from you. Please add your web page URL to the database via this form. You can drop me a line if you like. If you are having any problem with the program, please let me know as well. Feel free to send any suggestion. If you think that the program is cool, please consider sending me a picture postcard of the area where you live. Thanks to all of you who sent me the nice postcards. I get enormous number of thank mails everyday, it's amazing. I really appreciate it.

    Muhammad A Muquit
    SEMCOR, Inc.
    65 West Street Road
    Warminster, PA 18974
    USA
Thanks.

Enjoy!

ChangeLog

If you contributed or suggested something and if your name is not here, please drop me a line and get the credit.

Thanks to John Anthony Ruchak for beta testing Count 1.5.

Count 1.5 (September 11, 1995, 9:00 PM EDT)

Count 1.4 (August 27, 1995)

Count 1.3

muquit@semcor.com

Last Update: September 17, 1995

Home Page