#!/usr/bin/perl -Tw
#
#NAME
#  listcoll - Web directory-listing script
#
#SYNOPSIS
#  http://host.dom.ain:port/CGI/wca/listcoll/~name/some/dir/
#
#REQUIRES
	$version = '20140921';	# Which version we claim to be
	require &LocalSetup(1);	# Figure out localization stuff
	require "taintsubs.pm";	# Routines for handling tainted data
#
#DESCRIPTION
#  This is a CGI script that looks for certain hosts in the client info,
#  and sends them a message.  It also prints out a dump of all its HTML
#  form fields, and its environment.
#
#  This program really is a sort of prototype and sanity test.
#
#OPTIONS
#
#FILES
#
#BUGS
#
#SEE ALSO
#
#AUTHOR John Chambers <jc@trillian.mit.edu>

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Some basic globals:

use feature 'unicode_strings';
$| = 1;				# Immediately flush STDOUT
$exitstat = 0;		# Set to nonzero to "fail"
$P = 'list';		# Default name of this program
$Pname = 'list.pl';	# More detailed name of this program
$V = 1;				# Default verbose level
$Vsrc = 'default';	# Our verbose level's origin
@Send = ();			# Stuff to send after after we're in the <BODY>

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Make sure that our working directory  for  every  machine  is  one  of  the
# following:
	if    (-d ($d = '/home/jc/w'))             {$webdir = $d; $baseuri = '/~jc';}	# Most unices
	elsif (-d ($d = '/u/guests/jc/w'))         {$webdir = $d; $baseuri = '/~jc';}	# trillian
	elsif (-d ($d = '/Users/jc/w'))            {$webdir = $d; $baseuri = '/~jc';}	# OS X
	else  {print STDERR "$P: Can't find home directory.\n"; exit -1}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Our globals:

$B = 1;			# Whether to draw table borders
$PATH = '/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/sbin:/usr/sbin';
@cgi = ();		# Names in our CGI form data
$cgi = 0;		# A ref to our CGI form data
$T = '';		# Rembers a tune title
$basedir = '?';	# Try to get to the user's web directory ...
$listdir = '?';	# Gets the directory that we list
@vals = ();
$x = 0;
#file;
#files;
#line;
#botname;
#cwd = '??';
#hms = '??';
#msg = '??';
#UA  = '??';
#ymd = '??';
$HDRsent = 0;	# Whether we've sent a HEADER file

my(%fileInfo) = ();	# HTMl fields for the current file
my($fileline);		# Gets a line of HTML about a file
my(@listCol) =		# Table column order
	('T','D','S','F','N','abcX','abcM','abcK','abcR','abcT','ERR');
my(%showCol) = (	# Table column on/off flags
	'D' => 0,		# date last changed
	'N' => 1,		# name
	'F' => 0,		# fmt  
	'S' => 1,		# size
	'T' => 1,		# type
	'abcX' => 1,	# ABC X: field(s)
	'abcM' => 1,	# ABC M: field(s)
	'abcR' => 1,	# ABC R: field(s)
	'abcK' => 1,	# ABC K: field(s)
	'abcT' => 1,	# ABC T: field(s)
	'ERR' => ($V>1?1:0),	# Error messages, if debugging
);
my(%nameCol) = (	# Table column header text
	'D' => "date",	# Last-written date
	'N' => "name",	# File name
	'F' => "fmt",	# Link to format the file for display
	'S' => "size",	# Size in bytes
	'T' => "type",	# Type, i.e., suffix or "dir"
	'abcX' => "X:",	# ABC header fields ...
	'abcM' => "M:",
	'abcR' => "R:",
	'abcK' => "K:",
	'abcT' => "T:",
	'ERR'  => "err",
);
my(%HIDE) = (		# Names of files we'd like to hide
	"index.cgi" => 1,
	"index.html" => 1,
	"index.shtml" => 1,
);

$ENV{PATH} = $PATH;
chomp($cwd = `pwd`);

#push @INC, '.';

use CGI;
use CGI::Carp 'fatalsToBrowser';
use diagnostics;

($Pname = $0) =~ s".*/"";	# This program's name, minus directories
($P = $Pname) =~ s/\..*$//;	# Strip off suffix
$x = $ENV{"V_$P"};
if (defined ($x) && ($x =~ /^(\d+)/)) {	# Our verbose level from environment
	$V = int($1);		# Use it if numeric
	$Vsrc = "ENV{V_$P}";
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
$cgi = new CGI;			# Whatever CGI info aour caller passed us.
@cgi = $cgi->param();
$x = $cgi->param("V");
if (defined($x) && ($x =~ /^(\d+)/)) {	# Our verbose level from form params
	$V = int($1);	# Use it if numeric
	$Vsrc = "cgi{V}";
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
$uri = $ENV{"REQUEST_URI"} || '??';
push @Send, "$P: \"$0\" \"$P\" version=$version.<br>" if $V>0;
push @Send, "$P: cwd=\"$cwd\"<br>" if $V>1;
push @Send, "$P: uri=\"$uri\"<br>" if $V>1;
my $scriptname = $ENV{"SCRIPT_NAME"} || '';
push @Send, "$P: scriptname=\"$scriptname\"<br>" if $V>1;
my $scriptpath = $ENV{"SCRIPT_FILENAME"} || '';
push @Send, "$P: scriptpath=\"$scriptpath\"<br>" if $V>1;
my $pathinfo = $ENV{"PATH_INFO"} || '';
push @Send, "$P: pathinfo=\"$pathinfo\"<br>" if $V>1;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Now for the tricky part: We Try to find  the  requested  directory  in  the
# current  machine's  file  system.   Since  different web servers and system
# managers have different ideas about where things should  be  installed  and
# what users' web directories should be called, we need to look around a bit.
# Note that, to go along with perl's taint checking, we  only  try  to  enter
# directories whose names are alphanameric.  We should try this with names in
# Chinese or Japanese just for fun ...

push @Send, "$P: webdir=\"$webdir\"<br>" if $V>0;
push @Send, "$P: baseuri=\"$baseuri\"<br>" if $V>0;
if ($scriptpath =~ s"^(.*)(/[^/]*)$"") {	# We start where this script is installed ...
	($basedir = $1) =~ s"/abc$"";
	$basedir =~ s"/cgi$"";
	push @Send, "$P: basedir=\"$basedir\"<br>" if $V>1;
}
$listdir = $basedir;	# Try to get to the user's web directory ...
push @Send, "$P: listdir=\"$listdir\"<br>" if $V>1;
if (-d $listdir) {		# Our first guess ...
	if (chdir($listdir)) {
		chomp($cwd = `pwd`);
		push @Send, "$P: cwd=\"$cwd\"<br>" if $V>1;
	} else {
		push @Send, "$P: Can't chdir to $listdir ($!)<br>" if $V>0;
	}
}
$pathuri = $baseuri;
push @Send, "$P: Try pathinfo=\"$pathinfo\"<br>" if $V>2;
push @Send, "$P: Try baseuri=\"$baseuri\"<br>" if $V>2;
($diruri  = "$baseuri$pathinfo") =~ s"/+$"";
push @Send, "$P: diruri=\"$diruri\"<br>" if $V>0;
# Now we go through the PATH_INFO and see how much of it is a list of directories:
dir:
while ($pathinfo && ($pathinfo =~ s"^/*(\w+)/*"")) {
	push @Send, "$P: Try \"$1\" ... " if $V>2;
	if (chdir($1)) {
		$pathuri .= "/$1";
		($cwd = `/bin/pwd`) =~ s/[\r\s]+$//;
		push @Send, "cwd=\"$cwd\" pathuri=\"$pathuri\"<br>" if $V>2;
	} else {
		push @Send, "$P: Can't chdir to $cwd/$1 ($!)<br>" if $V>0;
		last dir;
	}
}
push @Send, "$P: cwd=\"$cwd\" pathuri=\"$pathuri\"<br>" if $V>0;
push @Send, "$P: pathinfo=\"$pathinfo\" not reachable.<br>" if $pathinfo && $V>1;
# If there's anything left in pathinfo, it's something odd that isn't our directory

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Try to find a reasonable title saying what we're listing:

# First, a .info file may contain the directory's title:
if (-f '.info') {	# Does this directory have an info file?
	print STDERR "$P: Call readInfo() ...\n" if $V>8;
	&readInfo();			# Extract data from it.
} else {
	print STDERR "$P: No .info file found.\n" if $V>3;
}
# If that didn't give us a title, make up something useful:
unless ($T) {
	print STDERR "$P: Figure out a title ...\n" if $V>3;
	if (!$T && defined($T = $ENV{"REQUEST_URI"})) {
		print STDERR "$P: REQUEST_URI found.\n" if $V>3;
		$T =~ s"\?.*"";
		$T =~ s".*/\~*jc/"";
		$T =~ s"/[^/]*$"";
		push @Send, "Title \"$T\" from REQUEST_URI<br>\n" if $V>5;
	} else {
		print STDERR "$P: Default title is our directory.\n" if $V>2;
		($T = `/bin/pwd`) =~ m"^.*/jc/(.*)/*[^/]*$";
		$T = $1 || '[unknown]';
		push @Send, "Title \"$T\" from /bin/pwd<br>\n" if $V>5;
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
print "Content-type: text/html\n\n";
print "<html><head><title>$T</title></head>\n";
print "<body><center><B><BIG>$T</BIG></B> [V=$V $Vsrc]</center>\n";
print "This program's name is \"$Pname\", or \"$P\" for short. V=$V ($Vsrc).<br>\n" if $V>1;

&sendSend();

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Note some stuff that we will probably need later.

$RA = &tIPad($ENV{REMOTE_ADDR});			# Client's IP address
$SA = &tIPad($ENV{SERVER_ADDR});			# Our IP address
$SP = &tInt($ENV{SERVER_PORT},80);			# Our server port
$SH = &tFQDN($ENV{SERVER_NAME},$SA);	 	# Our machine's name
$HH = &tFQDN($ENV{HTTP_HOST},$hostname); 	# Our machine's virtual host name
print "Client	RA='$RA' V=$V." if $V>0;
print "Server	$SA:$SP '$SH'" if $V>1;
print "Host	HH='$HH'" if $V>1;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Conditionally show our environment and form data:
&dumpEnv() if $V>1;
&dumpForm() if ($V>1 && @cgi);
print "cwd: $cwd<br>\n" if $V>1;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

&getDir();		# Figure out our working directory
&sendSend();	# Send any accumulated messages

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Check for known bots, and reject their request if they've asked for a  tune #
# match.   But we don't discriminate against them here; we just announce that #
# we think they're a bot.                                                     #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
if ($UA = $cgi->param('HTTP_USER_AGENT')) {
	if ($UA =~ /([-\w]*Google\w*|Yahoo. \w*)/) {
		$botname = $1;
		my($ss,$mm,$hh,$DD,$MM,$CY) = gmtime(time);
		$CY += 1900;
		$ymd = sprintf("%d-%02d-%02d",$CY,1+$MM,$DD);	# CCYY-MM-DD
		$hms = sprintf("%02d:%02d:%02d",$hh,$mm,$ss);	# HH:MM:SS
		$msg = "[$ymd $hms] $$ $0: Request from \"$botname\" bot.";
		print STDERR "$msg\n";	# Tell the errlog about it
		print        "$msg\n";	# Tell the client about it
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
print "<hr>Our PATH is \"$PATH\"<br>\n" if $V>1;
print "Our current directory is \"$cwd\"<br>\n" if $V>1;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Read the file names in the current directory and search for special files:

@files = `ls`;
file:
for $file (@files) {
	$file =~ s/[\r\s]+$//;
	if ($file eq 'HEADER.html' || $file eq 'HEADER') {
		$HIDE{$file} = 1;	# Don't show it in the list
		print "Header file \"$file\" spotted.<br>\n" if $V>2;
			next file if $HDRsent;
			if (open(HDR,$file)) {
			while ($line = <HDR>) {
				print $line;
			}
			close HDR;
			$HDRsent ++;
		} else {
			print "$P: ### Can't read \"$file\" ($!)<br>\n";
		}
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
print "<hr>Now on to our task ... <br>\n" if $V>2;

$showCol{'ERR'} = ($V > 1);	# Turn off ERR collumn for low verbose levels
if (@files = `ls`) {
	print "<center>\n";
	print "<table border=$B style='border-collapse:collapse'>\n";
	print "<tr>" . &colHdrs() . "</tr>\n";
file:
	for $file (@files) {
		$file =~ s/[\r\s]+$//;
		next file if $HIDE{$file};
		%nameInfo = ();			# Forget any info about previous file
		$fileline = &fileInfo($file);
		print "<tr>\n";			# Now we try to recognize a few kinds of files:
		print "\t$fileline\n";
		print "</tr>\n";
	}
	print "</table>\n";
	print "</center>\n";
}



# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
print "<hr></body></html>\n";
exit $exitstat;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

sub colHdrs {my $F='colHdrs';
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local ($c,$v,$hdrs);
	for $c (@listCol) {
		if ($showCol{$c}) {
			$hdrs .= "<th>" . $nameCol{$c} . "</th>";
		} else {
			$hdrs .= "<th></th>";
		}
		print "$F: c='$c' hdrs=\"$hdrs\"<br>\n" if $V>8;
	}
	return $hdrs;
}

sub dumpEnv {
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local($e,$v);
	print "<hr>Here are our environment variables:\n";
	print "<dl compact>\n";
	for $e (sort keys %ENV) {
		$v = $ENV{$e};
		print "<dt>$e<dd>$v\n";
	}
	print "</dl>\n";
} 

sub dumpForm {
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local($n,$v);
	print "<hr>Here are our form elements:\n";
	print "<dl compact>\n";
	for $n (sort @cgi) {
		if (@vals = $cgi->param($n)) {
			for $v (@vals) {print "<dt>$n<dd>\"$v\"\n"}
		} elsif ($v = $cgi->param($n)) {
			print "<dt>$n<dd>\"$v\"\n";
		} else {
			print "<dt>$n<dd>(NO VALUE)\n";
		}
	}
	print "</dl>\n";
}

sub fileInfo {my $F='fileinfo'; local($name) = @_;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Get the info we want for a file, and fill in the fields in  %fileInfo  with #
# the HTML strings for each field.  The fields we handle so far:              #
#   T=type  the kind of info in the file
#   S=size  the size in bytes
#   N=name  the filename, usually as a hyperlink
#   F=fmt   not implemented yet (invokes ABC-to-PS/PDF/PNG/... conversion)
#   D=date  not implemented yet (the file's last-change time)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local($c,$html,$link,$mtime,$size,@stat,$nameuri);
	local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst,$utdt);
	%fileInfo = ();
#	($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)
	@stat  = stat($name);	# Get the file's data
	$size  = $stat[7] || -1;
	$mtime = $stat[9];
	if ($showCol{'D'}) {
		($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($mtime);
		$year += 1900; $mon++;
		$utdt = sprintf("%04d-%02d-%02d %02d:%02d:%02d UT",$year,$mon,$mday,$hour,$min,$sec);
	} else {
		$utdt = '';
	}
	$nameuri = "$diruri/$name";
	$nameInfo{D} = "<td align=right>$utdt</td>";
	$nameInfo{S} = "<td align=right>$size</td>";
	$nameInfo{N} = $name;	# The plain file name, usually rewritten
	# The T=type column is the complicated one:
	if (-d $name) {			# Directory
		$nameInfo{T} = '<td>dir</td>';
		$link = "<a href=\"$name/\">$name</a>/";
	} elsif (-x $name) {	# Executable program
		if ($name =~ /\.cgi\b/i) {	# CGI program
			$nameInfo{T} = '<td>cgi</td>';
			$link = "<a href=\"$nameuri\">$name</a>*";
		} else {			# Random program
			$nameInfo{T} = '<td>prg</td>';
			$link = "<a href=\"$nameuri\">$name</a>*\n";
		}
	} else {
		if ($name =~ /\.abc\b/i) {	# ABC music file
			$nameInfo{T} = '<td>abc</td>';
			$link = "<a href=\"$nameuri\">$name</a>";
			&ABCinfo($name);
		} elsif ($name eq 'HEADER.html' || $name eq 'HEADER') {
			$nameInfo{T} = '<td>hdr</td>';
			unless ($HDRsent) {	# Did we spot the header and send it?
				$link = "<a href=\"$nameuri\">$name</a>$!";
			}
		} else {			# Random data file
			$nameInfo{T} = '<td>data</td>';
			$link = "<a href=\"$nameuri\">$name</a>";
		}
	}
	$nameInfo{N} = "<td>" . ($link || '??') . "</td>";
	$html = '';
	for $c (@listCol) {
		$html .= $nameInfo{$c} || "<td></td>";
	}
	return $html;
}

sub ABCinfo {my $F='ABCinfo'; local($f) = @_;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Open a file and (try to) extract ABC header info.  What we find is put into #
# the global nameInfo{} table.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local($l,$r);
	local($ERR,$abcX,$abcM,$abcR,$abcK,$abcT,$abcX) = ('','','','','','','');
	unless (open(F,$f)) {
		$nameInfo{'ERR'} .= "<td>### can't open $f [$?] ###</td>\n";
		return 0;
	}
	$r = 0;		# Count the headers matched.
hdr:
	while ($l = <F>) {
		$l =~ s/[\r\s]*$//;
		if ($l eq '') {	# Blank line ends tune.
			close F;
			return $r;
		} elsif ($l =~ /^X:\s*(.*)$/) {
			$abcX = $abcX ? "$abcX<br>$1" : $1;
			print STDERR "$P: X: \"$abcX\"\n" if $V>3;
		} elsif ($l =~ /^M:\s*(.*)$/) {
			$abcM = $abcM ? "$abcM<br>$1" : $1;
			print STDERR "$P: M: \"$abcM\"\n" if $V>3;
		} elsif ($l =~ /^%*R:\s*(.*)$/) {
			$abcR = $abcR ? "$abcR<br>$1" : $1;
			print STDERR "$P: R: \"$abcR\"\n" if $V>3;
		} elsif ($l =~ /^K:\s*(.*)$/) {
			$abcK = $abcK ? "$abcK<br>$1" : $1;
			print STDERR "$P: K: \"$abcK\"\n" if $V>3;
			close F;	# K: terminates header
			last hdr;
		} elsif ($l =~ /^T:\s*(.*)$/) {
			$abcT = $abcT ? "$abcT<br>$1" : $1;
		#	$abcT =~ s'\`a'à'g;		# Do these work?
		#	$abcT =~ s'\251''g;		# Apparently not
			print STDERR "$P: T: \"$abcT\"\n" if $V>3;
		} elsif ($l =~ /^B:\s*(.*)$/) {
		} elsif ($l =~ /^F:\s*(.*)$/) {
		} elsif ($l =~ /^N:\s*(.*)$/) {
		} elsif ($l =~ /^Z:\s*(.*)$/) {
		} elsif ($l =~ /^%\s*(.*)$/) {
		} else {
			print STDERR "$P: DROP \"$l\"\n" if $V>3;
			;	# Ignore the rest
		}
	}
	$nameInfo{'abcX'} = "<td>$abcX</td>";
	$nameInfo{'abcM'} = "<td>$abcM</td>";
	$nameInfo{'abcR'} = "<td>$abcR</td>";
	$nameInfo{'abcK'} = "<td>$abcK</td>";
	$nameInfo{'abcT'} = "<td>$abcT</td>";
	$nameInfo{'ERR'}  = "<td>$ERR</td>";
	return $r;
}

sub getDir {
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Figure out what directory (relative to $webdir) that we're to list.  If the
# PATH_INFO  string  exists, we'll use it, so the user can name the directory
# in the URL.  Otherwise, we look for the HTTP_REFERER string, which browsers
# should  send us.  This way, an HTML file can just link to this program, and
# the "current" directory will be listed.  Don't call this before we've sent
# the HTTP and HTML header stuff.
#
	($PI = $ENV{PATH_INFO} || '') =~ s"^/+"";
	push @Send, "PI=\"$PI\"<br>" if $V>0;
	if ($PI) {
		push @Send, "Using PATH_INFO \"$PI\"<br>" if $V>0;
		push @Send, "PI=\"$PI\"<br>" if $V>0;
	} elsif (($PI = $ENV{'HTTP_REFERER'}) && ($PI =~ m"/$")) {
		push @Send, "Using HTTP_REFERER \"$PI\"<br>" if $V>0;
		$PI =~ s"^http://([\w.:]+)/"";
		$HP = $1;
		push @Send, "PI=\"$PI\" HP=\"$HP\"<br>" if $V>0;
		$PI =~ s"^~\w+"";		# Strip out user id
		push @Send, "PI=\"$PI\"<br>" if $V>0;
		($vhost = $HP) =~ s/:.*$//;
		push @Send, "PI=\"$PI\" vhost=\"$vhost\"<br>" if $V>0;
	} elsif ($PI = $data{D} || $data{DIR} || $data{DIR1} || $data{DIR2}) {
		push @Send, "Using DIR \"$PI\"<br>" if $V>0;
		$PI =~ s"^http://[\w.:]+/"";
		push @Send, "PI=\"$PI\"<br>" if $V>0;
		$PI =~ s"^~\w+"";		# Strip out user id
		push @Send, "PI=\"$PI\"<br>" if $V>0;
	} else {
		$PI = '';
	}
	if ($PI =~ m"^/*(.*)/*$") {
		$pathinfo = "$1";	# Untaint the path info
	} 
	push @Send, "pathinfo=\"$pathinfo\"<br>" if $V>0;
}

sub LocalSetup { $Vtest = shift;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Figure out where we're running, and try to require a *cgilocal.pm file  for #
# local  settings.   The  end  result of this is to initialize a long list of #
# global variables.  The return value is the name of the cgilocal file, which #
# we usually feed to the 'require' command.                                   #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	$ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin';
	push @INC, '.';
	$testing = '0';	# Set to 1 while testing
	umask 0002;		# Output files must be group writable
	$| = 1;			# Unbuffered STDOUT
	$" = ',';		# Used in verbose messages
	($P = $0 || 'filelist') =~ s".*/"";
	(($ENV{"V_$P"} || $ENV{"D_$P"} || $testing) . ' 1') =~ /(\d+)/;	# Verbose level
	$V = $1;
	($ENV{REMOTE_ADDR} || '0.0.0.0') =~ m/^\s*([\d.]+)\s*$/;
	$RA = $1;
	if (defined($x = $data{V}) && ($x =~ /^\s*(\d+)\s*$/)) {
		$V = $1;
		&lsend("V=$V (from data).\n") if $V>3;
	} elsif ($RA eq '207.172.223.184') {	# My home machine
		$V = $Vtest if $V<$Vtest;
	} elsif ($RA =~ /^192\.168\./) {	# My home network
		$V = $Vtest if $V<$Vtest;
	}
	local($ss,$mm,$hh,$DD,$MM,$YY) = gmtime(time);		# Current date/time
	$ymd = sprintf("%d-%02d-%02d",1900+$YY,1+$MM,$DD);	# CCYY-MM-DD
	$hms = sprintf("%02d:%02d:%02d",$hh,$mm,$ss);		# HH:MM:SS
	$hostname = `/bin/hostname`;		# What does this machine call itself?
	$hostname =~ s/^\s*([-.\w]*)([\r\s]*)$/$1/;		# Strip off domain info
	($host = $1) =~ s/\..*//;			# Extract first field of name
	$cwd = `/bin/pwd`;
	$hstloc = $host . "-cgilocal.pm";
	$cgiloc = (-f $hstloc) ? $hstloc : 'cgilocal.pm';
	return $cgiloc;
}

sub readInfo {my $F='readInfo';
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# We attempt to read a .info file, which may contain info that we  can  share #
# with  the  client.   We  may  put stuff into @Send here, but the <HEAD> and #
# <BODY> tags may not have been sent yet,  so  we  shouldn't  print  anything #
# directly to the client.                                                     #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local($l);
	if (open(INFO,".info")) {
#		push @Send, "$F: Reading .info file ...<br>" if $V>1;
line:	while ($l = <INFO>) {
			$l =~ s/[\r\s]$//;	# Trim away white stuff
#			push @Send, "$F: LINE \"$l\"<br>" if $V>4;
			next line if $l =~ /^\s*#/;
			next unless $l;		# Ignore blank lines
			if ($l =~ /^(V):\s*(\d+)/) {		# Verbose level
				if ($V < $2) {	# Only use if higher than we already have
					$V = int($2) if $2 > $V;
					$Vsrc = ".info file";
				}
#				push @Send, "$F: V=$V.<br>" if $V>1;
			} elsif ($l =~ /^(T|Title):\s*(.*)/) {	# Directory title
				$T = $2;		# Note: This may be null
#				push @Send, "$F: T=\"$T\" from .info file.<br>" if $V>1;
			} else {
#				push @Send, "$F: Ignore \"$l\"<br>" if $V>2;
			}
		}
	} else {
		print STDERR "$P/$F: Can't read .info file [$!]\n";
		push @Send,"$F: ### Can't read .info file [$!]<br>";
	}
}

sub sendSend() {
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	if (@Send) {
		print "There's data in the Send list ...<br>\n" if $V>1;
		foreach $line (@Send) {
			print "$line\n";
		}
	}
	@Send = ();
}

