ZiaTioN has asked for the wisdom of the Perl Monks concerning the following question:

I wrote a simple script to log all visitors IP addresses and embedded the calling of the script in an image tag. However when I visit the page the script is never executed.

Here is the code:

#!/usr/bin/perl $file = "/home/master/webroot/perlskripts/ip.log"; if (-e $file) { open(lg, ">>$file") || die "Can't open $file!\n"; print lg "User from ".$ENV{'REMOTE_ADDR'}." logged on\n"; close(lg); }else{ $create = `touch $file`; $chmod = `chmod u+rw $file`; open(lg, ">>$file") || die "Can't open $file!\n"; print lg "User from ".$ENV{'REMOTE_ADDR'}." logged on\n"; close(lg); }
Here is how I call it in my web page:
<tr bgcolor="#220E50"> <td> <img src="/var/www/cgi-bin/remote_address.pl" height="0" width="0" +alt="[script]"> </td> </tr>
Any ideas as to why this would not be executed. I am pretty sure the image embedding method is valid. Alos when I run the script via command line it does what it is suppose to do.

Replies are listed 'Best First'.
Re: Simple script not being executed when html page loads.
by duct_tape (Hermit) on Dec 24, 2003 at 16:12 UTC

    Your image tag is pointing to the actual path to the file on the server, instead of the path relative to the webroot? Try change it to point to /cgi-bin/remote_address.pl instead and see if that helps.

    Brad
Re: Simple script not being executed when html page loads.
by jeffa (Bishop) on Dec 24, 2003 at 17:07 UTC
    A few pointers:
    • My web server is set up to execute files that have a .cgi extension as CGI scripts. Only. Your web server my be set up the same way. Try changing the name of your CGI script to remote_address.cgi
    • Your CGI script should always print a Content Header. Even though you don't "have to" in this case, know that everytime the script is execute an error is being generated in the error log.
    • Opening a file in append mode will create the file if it doesn't exist. You can trim your 12 lines of code down to 3. Also, be sure that the file has the proper permissions or the web server will not be able to write to it. I recommend touching the file ip.log in the directory of choice, su'ing to root, chown the group to the web server, and then chmod the file to 664. If you don't have root access, you can't chown the file and you will have to chmod it 646 or 666.
    Having said all of that, here is the CGI script rewritten:
    use strict; use warnings; use CGI qw(header); my $file = '/full/file/path/to/ip.log'; open LOG, '>>', $file or die "can't open ip log: $!\n"; print LOG "$ENV{REMOTE_ADDR}\n"; print header('image/png');
    You do want to call the CGI script via it's URL, not it's file path. Good luck. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Simple script not being executed when html page loads.
by cees (Curate) on Dec 24, 2003 at 18:15 UTC

    There are a coupld of issues with this script that you could improve:

    • You may need to set the PATH environment variable, or have the full path you your 'touch' and 'chmod' programs (or better yet, let 'open' create the file for you, and why not use the built in perl version of 'chmod').
    • Check to make sure that the webserver can actually write to the directory that you have listed. Remember that the web server may run as a different user than what you normally use.
    • You are not locking the file when you are writing to it. If you have two requests to this script concurently you could mess up the file.
    • You are not returning anything to the browser. You need to return an image of some sort, and a full set of headers.

    Here is your script with file locks. It always returns a clear gif to the browser even if the open failed.

    #!/usr/bin/perl use Fcntl ':flock'; use MIME::Base64; use CGI qw(header); my $file = "/home/master/webroot/perlskripts/ip.log"; if ( open(my $fh, '>>', $file) ) { # lock the file flock($fh,LOCK_EX); # seek to the end in case someone altered # the file since we opened it seek($fh, 0, 2); # add the entry to the file print $fh "User from ".$ENV{'REMOTE_ADDR'}." logged on\n"; # unlock flock($fh,LOCK_UN); } else { print STDERR "Could not open file for append: $!\n"; } # always send a clear gif to the browser my $q = CGI->new(); $q->header(-type => 'image/gif'); # The following is a base64 encoded 1x1 clear gif image print MIME::Base64::decode_base64('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAA +ALAAAAAABAAEAAAICRAEAOw==');

    - Cees

Re: Simple script not being executed when html page loads.
by b10m (Vicar) on Dec 24, 2003 at 16:14 UTC
    <img src="/var/www/cgi-bin/remote_address.pl" height="0" width="0" alt="script">

    Just a quick shot in the dark: are you sure you want "/var/www/cgi-bin/remote_address.pl" and not something more like "/cgi-bin/remote_address.pl"?

    --
    b10m
Re: Simple script not being executed when html page loads.
by inman (Curate) on Dec 24, 2003 at 16:13 UTC
    It's probably that the browser figures that it can't show an image of height=0 and width=0 so it doesn't bother trying to call the script. Try modifying the image tag so that it loads a 1x1 pixel transparent gif returned by your logging script.

    Update: While you are developing the code you might want to work with a larger, visible image so that you can see whether script has run correctly.

    You should be aware that some privacy tools remove 1x1 pixel images loaded from third party sites on the grounds that loading the image can be used for tracking the user without their consent.