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

Here is statistic script, called from SSI. How to make this script works called from image tags?

#!/usr/bin/perl # This script saves access date+time, the visitor's host name, their I +P # address and browser type, and the refering page (if any) to a log fi +le # on your server (default name = logfile.txt). This file will be autom +atically # mailed to your mailbox. You can change the mailing interval accordin +g # to your needs (default value is every 50 accesses to the page to be # logged). The script will autocreate the logfile, if it does not exis +t. # don't change anything past this line unless you know what you are do +ing # -------------------------------------------------------------------- +--- # create a date+time string $shortdate = `date +"%D %T %Z"`; chop ($shortdate); # Some of Perl's network info functions required here ($part1,$part2,$part3,$part4)=split(/\./,$ENV{REMOTE_ADDR}); $IP_adr=pack("C4",$part1,$part2,$part3,$part4); ($host_name)=(gethostbyaddr("$IP_adr", 2)); #print "Content-type: text/plain\n\n"; if ($check_host) { # read host and time info from last visitor if (-e "$hostfile") { open(HOST,"$hostfile"); $hostline = <HOST>; chop($hostline) if $hostline =~ /\n$/; close(HOST); ($old_time,$old_number,$old_page,$old_browser) = split(/\|/,$hos +tline); } # save host and time info and check if this is a page reload open(HOST,">$hostfile"); $seconds = time; print HOST "$seconds\|$ENV{REMOTE_ADDR}\|$ENV{'DOCUMENT_URI'}\|$ENV +{'HTTP_USER_AGENT'}"; close(HOST); if (time - $old_time < $interval && $ENV{REMOTE_ADDR} eq $old_number && $ENV{'DOCUMENT_URI'} eq $old_page && $ENV{'HTTP_USER_AGENT'} eq $old_browser) { exit; # probably same visitor, so exit } } # open log file for output and append new log data open (LOGFILE, ">>$logfile"); print LOGFILE "Time: $shortdate\n"; print LOGFILE "From: $ENV{'HTTP_REFERER'}\n"; print LOGFILE "IP : $ENV{REMOTE_ADDR}\n" if $log_IP; print LOGFILE "Host: $host_name\n"; print LOGFILE "With: $ENV{'HTTP_USER_AGENT'}\n"; print LOGFILE "Page: $ENV{'DOCUMENT_URI'}\n" if $log_page; print LOGFILE "\n"; close (LOGFILE); # open log file for input and count log entries open (LOGFILE, $logfile); @entries = <LOGFILE>; close (LOGFILE); $log_rows = 7; $log_rows-- unless $log_page; $log_rows-- unless $log_IP; $log_count = @entries/$log_rows; # if number of logs >= max. number of logs, mail file and delete it if ($log_count >= $max_entries) { open (MAIL, "|$mailprogam $recipient") || die "Can't open $mailprog +am!\n"; print MAIL "Subject: Mail-log File\n\n"; print MAIL "@entries\n"; close MAIL; unlink $logfile; } # end of script

Janitored by Arunbear - added readmore tags, as per Monastery guidelines

Replies are listed 'Best First'.
Re: Making script called from image tags
by jhourcle (Prior) on May 05, 2005 at 13:29 UTC

    There is no reason to use web server logging scripts. Any half-decent web server can log this information, without you needing to do anything special, other than a line or two in a configuration file and a restart:

    You can trigger the e-mail through whatever you have doing your log rotation, or send the logs to a process, rather than a file.

      <quibble>
      "There is no reason to use web server logging scripts."

      For those wretched, undeserving souls who rely upon a hosting service (as I and some of my clients do), "a line or two...and a restart" are not necessarily options.

      </quibble>
        ... and ++ re the rest...

        Most decent* hosting services will provide logging. Some hosts will give you a way to configure your own virtual host through what some of them call a 'control panel'.

        * -- those that actually care, and are customer oriented, as opposed to someone tossing up a server, for a place for you to dump your files, and trying to compete solely on price. You really do get what you pay for.

      A reply falls below the community's threshold of quality. You may see it by logging in.
      It from old German archives, time of perl programming formation.. Old time, old programmers.. What about the rest, is the script syntax correct? Or it's too clumsy also? You mean insert this this way? Is this correct:
      #print "Content-type: text/plain\n\n"; print "Content-type: image/x-xbitmap\n\n"; print "#define name_width 1"; print "\n"; print "#define name_height 1"; print "\n"; print "static char name_bits[] = { 0x04 };"; print "\n"; if ($check_host) { # read host and time info from last visitor ....
Re: Making script called from image tags
by Joost (Canon) on May 05, 2005 at 11:41 UTC
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Making script called from image tags
by Fletch (Bishop) on May 05, 2005 at 17:53 UTC

    I bet I'm not the only person getting sick of these repeated (nigh daily) requests for assistance with the panopoly of broken scripts you're managing to dredge up from the bowels of the web. TALK TO YOUR HOSTING PROVIDER AND GET ACCESS TO THE LOGS. You're paying them to provide you with a service. If they don't provide the services you need, find a better provider who can.

Re: Making script called from image tags
by starbolin (Hermit) on May 05, 2005 at 17:53 UTC

    I wouldn't even know where to start in debugging your script. I wouldn't know whether your problems are with the script or your server configuration. What errors does your script produce? You must add these two lines:

    use warnings; use strict;
    What, if anything is shown in your servers logs? Can you post a smaller script that demonstrates just the problem you are trying to solve?

    An excellent reference is: Troubleshooting Perl CGI scripts. You might try the step outlined there. Then, post what steps you've tried allong with the specific error text that you received. That way, I would have something to work from. Otherwise, I would be just shooting guesses out of my /dev/random.


    As we drew near the sloop's stern, our light threw shdows on the carved letters on its escutcheon, which spelled "Jack Tar's Revenge." I stood amazed at the strength of my mother's voice when she cried up to the pudgy starbolin, "Ahoy, 'Revenge. Inform your Captain Roger as Long Lucy would meet wi' him."
    "Molly of Tortuga" - Michael B. Stevens
      Its a good practice to improve the old concepts,codes, not all people can this.
      It's always pleasant to give a new life to an old approved scripts..
      About taking the logs from hosting provider--not convenient for millions webmasters.
      Have got some helpful advices concerning the logfile paths, thanks.
      Can the logfiles and hostfiles be placed in www directory,not in cg-bin(as specified in script source)?? Since they must be writable for everyone.
      Now about difficulties: what be the right way to implement calling this script from image tags, not from SSI? Please accompany your advice with a concrete code.
      -------------------------------------------------------
      Concerning the another script: need help to exclude own IP from logging.
      #!/usr/bin/perl $sendmail_path='/usr/lib/sendmail'; $to_address='email@domain.com'; #DONT CHANGE ANYTHING BELOW THIS LINE if (length($ENV{HTTP_X_FORWARDED_FOR})>1) { $xf=$ENV{HTTP_X_FORWARDED_ +FOR}; } else { $xf='NULL'; } $ra=$ENV{REMOTE_ADDR}; @numbs=split(/\./, $ra); $address=pack("C4", @numbs); $gothostbyaddr=gethostbyaddr($address, 2) +; $gt=gmtime; $head=$ENV{REMOTE_ADDR}; @tl=(85,78,73,46,68,69); ($gothostbyaddr) && ($head=$gothostbyaddr); if (length($ENV{QUERY_STRING})>1) { $reff=$ENV{QUERY_STRING}; } else {$reff=$ENV{HTTP_REFERER}; $reff=~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; } $head.=" $reff"; $from_address="a".$to_address; open(MH,"|$sendmail_path -t"); print MH "To: $to_address\nFrom: $from_address"; print MH "\n"; print MH "Subject: Visitor Info $head\n\nHTTP_REFERER $reff"; print MH "\n"; print MH "DNS $gothostbyaddr\nIP $ENV{REMOTE_ADDR}"; print MH "\n"; print MH "BROWSER $ENV{HTTP_USER_AGENT}\nWHEN $gt GMT"; print MH "\n"; print MH "FORWARDED_FOR $xf"; print MH "\n"; print MH "APPS $ENV{HTTP_ACCEPT}\n\n"; print MH "MVI CGI Script 1.3 http://mviscript.hypermart.net"; print "\n"; close MH; print "Content-type: image/x-xbitmap\n\n"; print "#define name_width 1"; print "\n"; print "#define name_height 1"; print "\n"; print "static char name_bits[] = { 0x04 };"; print "\n";
      ------------------------ Here i find two possible ways:
      1) wrapping IP in an if statment:
      if($ENV{REMOTE_ADDR} =~ '10.10.0.1') { the code }
      2)use logic:
      exit if ($ENV{REMOTE_ADDR} =~ '10.10.0.1');
      3) wrapping IP in an unless statment: another way
      unless ($ENV{REMOTE_ADDR} =~ '10.10.0.1') { the code }
      what is preferable way and how to implement it?(concrete sample required)
      thanks

        This last posting is much better Anonymous Monk, thank you.

        Posting a new question as a reply to a previous question is not the best way to get a quality response. Many Monks have become bored by now and have not read all the replies. This last post is written well enough to deserve a new node in SoPW.

        Please, feel free to obtain a Perlmonk username. That way I don't have to call you Anonymous Monk.

        "Its a good practice to improve the old concepts,codes, not all people can this."
        Perhaps, but it is less atractive to post old scripts here. We are more interested your level of understanding of the code. Seeing a script which the poster didn't write leads us to believe ( perhaps incorrectly ) the poster doesn't understand the code and has not taken the time to understand the code. Thus we Monks are less likely to take the time to understand what the poster is saying.
        "Can the logfiles and hostfiles be placed in www directory,not in cg-bin"
        They could be placed in any directory to which you're CGI script has read/write privleges. Usually, your host has very specific requirements as to where you can and cannot write files.

        Before posting, please run your scripts through perltidy. This:

        @tl=(85,78,73,46,68,69); ($gothostbyaddr) && ($head=$gothostbyaddr); if (length($ENV{QUERY_STRING})>1) { $reff=$ENV{QUERY_STRING}; } else {$reff=$ENV{HTTP_REFERER}; $reff=~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; } $head.=" $reff";
        Becomes this:
        @tl = ( 85, 78, 73, 46, 68, 69 ); ($gothostbyaddr) && ( $head = $gothostbyaddr ); if ( length( $ENV{QUERY_STRING} ) > 1 ) { $reff = $ENV{QUERY_STRING}; +} else { $reff = $ENV{HTTP_REFERER}; $reff =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; } $head .= " $reff";
        So very much easier to read and even gives the reader the impression that you actually know what you are doing.
        "what be the right way to implement calling this script from image tags"

        I don't understand what you mean by "calling this script from image tags, not from SSI". If you are calling the script from an image tag then that constitutes a Server Side Include. Perhaps if you can outline the process steps you want to execute? Do you mean "deliver executeable payload via image upload" as in a trojan?

        If your script doesn't include these lines:

        use warnings; use strict;
        That tells us you haven't used the best tool available for finding errors in your script. Perl is the best tool available for finding errors in your scripts. Use warnings.
        "need help to exclude own IP from logging."
        Either of the block formats you presented is acceptable. Perhaps
        unless ($ENV{REMOTE_ADDR} =~ ?10.10.0.1?){ ... }
        is more perl like.


        s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}