WebCounter Apache Module 2.2.4

by Dan Kogai (dankogai@dan.co.jp)

Accessed times since . click here to see module status

Last Modified:



Introduction

Page counters are one of the most-frequently-used web programmings. It is easy with CGI and even easier with SSI (if you don't need image). There are tons of implementatonis available and it is considered trivial to implement basic ones.

Is that really so?

Yes, if you don't care the performance. CGI is a complete process which needs to be invoked, run, and creaned up. in that sense CGI is no different from hefty emacs. And you know how many times the cgi gets called for the busiest pages in the World Wide Webs.

Yes if you don't care the sloppiness. With web server taking care of all these dirty jobs, you can go as sloppy as you like with CGI. All you have to do is read and write stdin/out. Making it a part of web server program is a completely different story. When you die, the whole web server dies altogether.

So here it is, a non-trivial, no-nonsense web server module which does count tracking and even image all by itself. Enjoy.


Latest News

Bug reports are very welcome (as welcome as thank you note). Paches are even more welcome. Other thing welcome is the usage report--what platform you are using, how much performance gain (or losss) is achieved.

9-Dec-1998

Typo in typo in cntr/mod_cntr.module fixed.

Note 1.2.x users: The ugly #include "gdimini.c" still remains (to make Configure happy) so if you are using apache 1.2.x AND PHP3 with GD support, the conflict still remains. Time is high you switched to 1.3.x, maybe...


Changes from ver 1.x

Though resulting counter faces look the same, it is now a different beast from head to foot. Read this section carefully if you are a ver 1.x user

Apache 1.3.x--savvy

It compiles both on 1.3.x and 1.2.x. It also supports APACI so it is automatically configured. It also supports DSO so you can add the module to binary distribution of Apache.

More efficient file format

WebCounter used to store values (count, date first accessed) in plain text. Now it stores these values in binary format (32bit x 2), resulting more efficiency.

In other words, the old counter file is NOT COMPATIBLE with the new one. But don't worry, I have conversion script ready for you. See below for more details.

Direct Image Rendering by the module

Yes, no cgi! With web server directly rendering counter image, it is far more efficient than cgi-based counter rendering. And even for those who would like to customize the counter program but too afreaid to dare touch the module, mod_cntr sets more environment variables to ease your programming.

No more bare-text counter file

Bare-text counter files are too innefficent so I have dropped the support. Sorry but if you are content with bare (CGI/SSI-based) counters with bare speed, there are tons of alternatives (many of which can be found athttp://www.digitmania.com/) as a result,(Server)CounterType directive is gone.

Per-directory configuration

All directives and handlers are now configurable per-directory basis. You can customize these with .htaccess file. That way, non-root users can use thier own customization. Side-effect of this change is the complete disappearance of ServerCounter* directives. They are all integrated with Counter* counterparts.

Indepenedent of cgi-lib.pl by Steven E. Brenner

Some of aux. scripts bundled in the package used to depend on cgi-lib.pl, a famous pre-perl5 cgi library. With perl 5.004 or later, CGI,pm comes standard so no extra package is needed to get full feature of the package

Name Changes in query string

In addition to handlernize image rendering engine, I have renamed variables in more approprate, less confusing manners. Here is a List.

New Old Description
face= type= Digit face. Used to be called "Digit Type" but the word "type" is more ambiguous and confusing.
path-info url= URL overriding when referer is not available
ndigit= length= Number of digits rendered.
fcount= count= Faked count. To punctuate the fact it is a fake, I have put "f" on the head.
trans (No Equivalent) Transparent color from topleft corner of the image. New feature.

There may be more but please read through.


Installation

Obtaining Source

You just lick the link on the right:http://www.dan.co.jp/software/webcounter-latest.tar.gz

When you get the tar ball above, just unpack it with

gzip webcounter-latest.tar.gz | tar xvf -

or

tar -zxvf webcounter-x.x.tar.gz

If your tar is GNU tar.

Compiling Apache

for 1.3.x

  1. copy entire cntr directory of this package into apache-1.3.x/src/modules where apache-1.3.x is the top of apache source tree.
  2. run

    ./configure --activate-module=src/modules/cntr/mod_cntr.c --other-config-direcives
    ...
    
    	
  3. Make at either src directory or the top of apache source tree.
  4. Make install

for 1.2.x

  1. copy all the c sources and headers of cntr directory (in other words, cntr/*.[ch]) into apache-1.2.x/src where apache-1.2.x is the top of apache source tree.
  2. add lines below to Configuration file;
    EXTRA_CFLAGS=-g -DHAVE_DB
    EXTRA_LIBS=-lm
    Module cntr_module mod_cntr.o
    

    where HAVE_DB is one of HAVE_DB, HAVE_GDBM, or HAVE_DBM depending on the DBM package you have. For *BSD, Berkely DB comes in standard so use HAVE_DB.

  3. run ./Configure.
  4. make

WebCounter 2.x is known to work with platforms below. If you have successfully compiled it and your platform is not listed here, please mail me a note.

Platform DBM Type Apache version Tested by:
1.2.x 1.3.x
Static DSO
FreeBSD 2.x DB OK OK OK dankogai@dan.co.jp
BSD/OS 2.1 DB OK OK OK dankogai@dan.co.jp
Linux 2.x GDBM ? OK OK steffann@nederland.net
dankogai@dan.co.jp
HP-UX 10.20/11.00 NDBM ? OK OK rv33100@GlaxoWellcome.co.uk
Solaris 2.x GDBM ? OK OK shaug@callamerica.net


Configuring httpd.conf

Here is a typical configuration for mod_cntr.c

# if you have made mod_cntr DSO, don't forget to add these
# if you have not, just comment these out
LoadModule cntr_module libexec/mod_cntr.so
AddModule mod_cntr.c

<IfModule mod_cntr.c>
CounterAutoAdd    On
CounterFile       logs/%v.count
CounterTimeFmt   "%A, %d-%b-%y %T %Z"
CounterFaceDir   /usr/local/apache/htdocs/digits
</IfModule>

<Location /server-cntr>
SetHandler server-cntr
</Location>

<Location /server-cntr-debug>
SetHandler server-cntr-debug
</Location>

And here is what each directives means.


Directives

CounterAutoAdd {On | Off}

Default: Off
Context: directory, .htaccess
Override: Any

This direcitve determines whether URIs nonexistent on the counter file be added. If On, new entry will be created on the counter file. If Off, nonexistent URIs are simply ignored.

CounterFile /path/to/counter/file

Default: None
Context: directory, .htaccess
Override: Any

You set the path to DBM file (without DBM suffix) here. Like many other directives whose value is path, you can use relative path here. for instance, if ServerRoot is /usr/local/apache and ServerCounterFile is logs/count, its absolute path will be /usr/local/apache/logs/count plus DBM suffix.

There is a %v macro which expands to virtualhost name (added by Sander Steffann).

Note: Remember owner of counter file is whatever you set in User directive (typically nobody). So the directory where counter file is stored must be writable by the user specified by User directive. This is the most common error so be carefuly!.

CounterTimeFmt "string-for-strftime()"

Syntax: see strftime(3)
Default: "%A, %d-%b-%y %T %Z"
Override: Any

Time format for URI_COUNT_RESET environment variable. As in "config timefmt=" of mod_include, format is the same as strftime(3).

CounterFaceDir /path/to/face/dir

Syntax: path to counter file (without DBM suffix)
Default: /usr/local/apache/htdocs/digits

Where counter seed graphics file are stored. see "The Face Files" below for details.


Handlers

From 2.1, mod_cntr not only updates the counter, it also renders the counter! Unlike CGI which has to read values via QUERY_STRING and other environment variables, handler directly grabs configs from module and renders the image, resulting more efficiency in time and resources.

To use this feature, you have to enable handler that does.

server-cntr

This is what replaces cgi. From the document, all you have to do is you insert <img src=/server-cntr>. See "Using Webcouter" below for usage.

server-cntr-debug

You can see what information gets passed to the handler using this handler. Click here to see what it does.


The Face Files

As explained above, WebCounter dynamically renders digit graphics from GIF files. In WebCounter 1.1, path to this file is can only be set compile-time. You can now do it with configuration directive CounterFaceDir so you can put it anywhere AS LONG AS IT IS READ-ACCESSBLE by httpd (normally user nobody).

Here is a directory hierarchy for seed files;

ServerCounterFacedir/
                      default/		Where default face files are stored
                              0.gif
                              1.gif
                              ...
                              9.gif
                      tiny/
                              0.gif
                              1.gif
                              ...
                              9.gif

WebCounetr comes with two digit faces, default and tiny. they are in digits directory so just copy them to whatever directory you spacified with the directive. If you don't know, just put it directly under DocumentRoot (that' sthe default). To specify which face to use, you give face=name query string. As you have correctly guessed, directory named name under CounterFaceDir will be used.

To see what faces are available, you can use show-digits.cgi perl script. No external library is used.

WebCounter-2.0 also comes with renamegif.pl perl script to convert digit files available at http://www.digitimania.com/ so you can add your favorite digit face.


Upgrading WebCounter-1.1 counter file

Unlike WebCouter-1.1 whose data are stored in text format, WebCounter-2.0 uses a fixed-width binary format for better performance and storage efficiency. In other words, 2.0 counter file is incompatible with 1.1.

Don't worry, though. I have added updatedbm.pl perl script to update counter file to 2.0 format. To do so, just

updatedbm.pl <path-to-dbm-file>

And it's done. Old counter file will be backed up as counter.old.dbmsuffix.


Using WebCounter

Once installed, WebCounter is really easy to use.

Graphical Counter

All you have to do is insert the tag below in the document

Indented part is an option that you can omit.

Synopsis:

<img src="/server-cntr/path/info?face=facename?ndigit=n?fcount=n?trans>

path-info

When server-cntr handler is called, it checks the referer and lookup appropriate uri. when it is a directory URI, it uses DirectoryIndex value to complete the URI (it snatches the setting of mod_dir.c. Though mod_cntr.c does work without it, I strongly suggest you link with it. Just leave it as the default and it will be included).

Though almost perfect, this might fail if the browser does not set Referer header. To compromise this, you can give additional path followed by /server-cntr (called path-info) and server-cntr will check it.

Example:
Tag Description Result
<img src=/server-cntr> Count of this page
<img src=/server-cntr/index.html> Count of /index.html

face=facename

This query specifies the alternate digit face for use. here, facename is a name of directory under CounterFaceDir directory where GIF files named 1.gif, 2.gif... are stored. When this directory is not found, the handler uses default face and logs the warning.

Example:
Tag Result
<img src=/server-cntr>
<img src=/server-cntr?face=tiny>

ndigit=number_of_digits

By default, server-cntr does not zero-fill the digit. With this set to non-zero, it forcibily renders this number of digits, with approprate numbers of zeroes.

Example:
Tag Result
<img src=/server-cntr?face=tiny&ndigit=10>

fcount=fake_count

You can spoof the count with this. fcount is short for faked counter. Give it any number.

Example:
Tag Result
<img src=/server-cntr?fcount=1234567890>

trans

A little nifty featue. When set (exists--you don't need to asign value with =value)The color of topleft (0,0) becomes transparent.

Example:
Tag Result
<img src=/server-cntr?face=tiny&trans>


SSI Variables

WebCounter sets environment variables below that you can use in SSI. These values are also helpful if you want to access counter via CGI. I have included perl version of count.cgi. that does the same as server-cntr handler. It requires GD.pm and URI::URL (comes with libwww) to run.

variable Description Example Result
URL_COUNT Access Count to the file <!--#echo var="URL_COUNT"-->

URL_COUNT_RESET When Access Count has started <!--#echo var="URL_COUNT_RESET"-->

URL_COUNT_DB Path to counter database. <!--#echo var="URL_COUNT_DB"-->

URL_COUNT_TIMEFMT Time format for URL_COUNT_RESET <!--#echo var="URL_COUNT_TIMEFMT"-->

URL_COUNT_FACEDIR Path to counter face files . <!--#echo var="URL_COUNT_FACEDIR"-->

URL_COUNT_DINDEX File names for directory index. <!--#echo var="URL_COUNT_DINDEX"-->


Counter Control Script

The script countctl.pl may be used to manipulate, reset, add, delete or view the counter logs. Make sure you have perl around. The countctl script is written assuming perl is located in /usr/local/bin/perl. If its in a different place, edit the first line to point to where your perl executable lies. Copy the script to either /usr/local/bin or where you plan to keep your counter log files. The script requires at least one argument, the hash or log filename. Certain options require the URL being processed.

The synopsis is as follows:

countctl.pl [ -cdrv URL ] filename 

    -c     create URL
    -d     delete URL
    -r     reset counter
    -v     view counter (and reset date)

If no option is supplied, it essentially dumps the contents of the file. The output is in no particular order. The format of the output is:

URL     count     reset_date

Caveat:

If you compiled mod_cntr with GDBM, countctl may not work. countctl.pl uses perl and there are cases where perl is not compiled with GDBM enabled. That was the case for most RedHat-based linux. Sigh....


Appendix

Still TODO

I think I have done all the homework but if you dare me give me more (more platform support, DB_BTREE and DB_RECNO supports, missing Japanese support once existed in ver. 1.1 you name'em), I am welcome to listen to your ideas.

History

The following changes have been made since release 1.0:

Version 2.2.4: by Armin Kunaschik (armin.kunaschik@PC-Plus.DE) and others
9-Dec-1998
Typo in typo in cntr/mod_cntr.module fixed.
Version 2.2.3: by Fabien Coelho (coelho@cri.ensmp.fr) and Dan Kogai
11-Nov-1998
* Incorrect #define in mod_cntr.c corrected; GDBM now works fine.
Version 2.2.2: by O'Shaughnessy Evans (shaug@callamerica.net) and Dan Kogai
9-Oct-1998
* Minor patch applied to "mod_cntr.module" to make it happy with /bin/sh of Solaris
* Updated the links without mailto: scheme.
Version 2.2.1: by Torsten Neuer (tneuer@inwise.de) and Dan Kogai
8-Oct-1998
Applied minor patch below to mod_cntr.c so CPP is happy when HAVE_DB is not defined.
Version 2.2: by Dan Kogai
6-Oct-1998
* Fixed confilicts w/ PHP3
* Bettrer configuration script
Version 2.1: by Dan Kogai
5-Oct-1998
* Too many to mention here. See Above.
Version 2.0b: by Sander Steffann (Unreleased)
Sep-1998
* Apach 1.3.x and APACI support
* GDBM support
* %v macro for CounterFile
Version 1.1-bsdi: by Dan Kogai
23-Nov-1996
* Japanese version of the instruction is also availble.
* Added a patch so that for BSDI, flock() is used instead of fcntl().
* Now correctly handles .db together w/ .dir/.pag for dbm log.
* Created following cgis to help users (requires cgi-lib.pl by Steven E. Brenner):
* show-digits.cgi
list and actually see the available digit
Version 1.1:
5-May-1996
Updated the countctl script to be able to set the current count of a page (in case a page or set of pages have moved between servers).
5-May-1996
Updated counter to *not* rely on correct SERVER_NAME and SERVER_PORT being set. This is for the case of either an IP address being sent or some other alias instead.

This code allows easy transparent use of web page counters.

Authours

By Dan Kogai (dankogai@dan.co.jp)with help of Sander Steffann (steffann@nederland.net). Originally by Braian Kolaci but at last virtually none of his codes are left. Original GD codes are done by Thomas Bourtell (boutell@boutell.com) and Lincoln D. Stein.

Acknowledgement

Not a few people have given me suggestions and some have even sent me codes ever since I took over WebCounter from Brian Kolaci. I would like to thank them all but namely;