#!/usr/bin/perl -- require 5; =item overview AXS Script Set, Administration Module Copyright 1997-2001 by Fluid Dynamics Please adhere to the copyright notice and conditions of use as described at the URL below. For latest version and help files, visit: http://www.xav.com/scripts/axs/ =cut my $VERSION = '2.3.0.0024'; my %FORM = (); my %PREF = (); my %const = (); my $all_code = <<'END_OF_CODE'; # You should place the log.txt and axs.dat files in the same directory as # this script. If you do, you won't have to change the variables below. # If you want to put the files somewhere else, enter the full path to these # files: $LogFile = 'log.txt'; $prefs = 'axs.dat'; # Other examples: # $LogFile = '/usr/www/users/xav/log.txt'; # $LogFile = 'c:/axs/log.txt'; # Enter your anchor page. This will form a link at the top of each AXS # output document: $link_url = '/'; $link_title = 'My Home Page'; # Once the script is working to your satisfaction, set the $AllowDebug # variable to zero: $AllowDebug = 1; # ________________________________________________________________________ # Protect AXS with a username and password. Both are case sensitive. You # can leave them blank to disable password locking. This is the default: $Username = 'leo.crawford'; $Password = 'Office'; # Other examples: # $Username = 'root'; # $Password = 'IronMAN'; # You can allow anyone access to your graphs, while continuing to protect # your "Customize" page with a username and password. If you do this, # web visitors will be free to view your statistics, but they won't be # able to delete the log file or change your settings. To allow web # visitors to see your graphs without entering a username or password, set # this to 1: $AllowAnonymousForGraphs = 1; # set to 1 to allow # ________________________________________________________________________ # Most of you shouldn't have to change anything below this line. If you # try the script out and it doesn't work, the help files will suggest # changes to the following lines. # The request method can be either GET or POST. Setting the method to GET # will cause the username and password data to be exposed to the web server # logs. Using GET is inadvisable if others have access to your web server # logs. $Request_Method = 'POST'; # The URL to this script: $This_Script_Address = &query_env('SCRIPT_NAME'); # The admininstrator's email address - use *single* quotes: $Admin_Email_Address = &query_env('SERVER_ADMIN', 'nobody@localhost'); # Example: # $Admin_Email_Address = 'president@whitehouse.gov'; # Your favorite network lookup services: $nslookup = 'http://www.xav.com/cgi-bin/nslookup.cgi'; $whois = 'http://www.xav.com/scripts/axs/whois.pl?a='; # Alternate (previous) whois script was: # $whois = 'http://www.networksolutions.com/cgi-bin/whois/whois?'; # AXS can collapse web addresses which include the default document. # This prevents you from having two database entries for a single file, # like http://www.ms.com/ and http://www.ms.com/index.html: $DefaultDoc = 'index.html'; # If you'd like, local files can show up as their HTML title instead of # their URL. For example, visits to http://www.xav.com/ would show up in # your graphs as "Home Page". To use this option, enter the URL-title # pairs below, and set the top variable to "1": $UseLocalAddressTitlePairs = 0; # Set to "1" to enable. %LocalAddressTitlePairs = ( 'http://www.xav.com/' , 'Home Page', 'http://www.xav.com/scripts/' , 'Scripts Page', 'http://www.xav.com/scripts/axs/' , 'AXS Script Page', ); # Uncomment this line if you receive errors about invalid Content-Type # headers. (to support command-line parameters, the HTTP headers are # only sent back if the SERVER_SOFTWARE env var is defined; most web # servers should set this, but if you're doesn't then you have to set # it manually by uncommenting the line below) #$ENV{'SERVER_SOFTWARE'} = 1; # No further editing is necessary, but feel free to play around. The # first 1,000 lines of this script are straight HTML and JavaScript, so # you can safely customize the look and feel of the output even if you # don't know Perl. # # ________________________________________________________________________ %GraphOptions = ( 's01' => 'Web Browser (Netscape 3.01 Gold)', 's02' => 'Abbreviated Browser (Netscape 3.X)', 's02a' => 'Browser Wars (Netscape)', 's03' => 'Operating System (Windows 98)', 's04' => 'Visitors Top Level Domains (.com)', 's05' => 'First Level Domains (xav.com)', 's06' => 'Full Server Address (noc.xav.com)', 's07' => 'Visitor IP Address (206.134.243.3)', 's08' => 'Hits from Other Sites (Full URL)', 's09' => 'Hits from Other Sites (Domain Only)', 's10' => 'Hyperlinks Followed From This Site', 's11' => 'Hits to Local Documents', 's12' => 'Average Number of Hits Per Visitor', 's13' => 'Hits By Day of Year', 's14' => 'Hits By Day of the Week', 's15' => 'Hits By Hour of the Day', ); @DatabaseOptions = ('Sort All by Time','Sort All by Visitor','Visitor Flow Only'); @LongWeekDays = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'); @ShortWeekDays = ('SUN','MON','TUE','WED','THU','FRI','SAT'); @LongMonths = ('January','February','March','April','May','June','July','August','September','October','November','December'); @ShortMonths = ('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'); @ShortDayNames = ('YEST','TOD','TOM'); $total_corrupt_rows = 0; sub Header { return <<"END_OF_HTML";
Main Menu - Customize - Log Out
EOM } print <<"EOM";AXS keeps records on visits to your site. This companion script, AX-ADMIN, allows you to display these records in meaningful graph and database formats. We currently have $cur_hits hits to work with. EOM foreach ('pl','cgi') { if (-e "ax.$_") { print "EOM } # ________________________________________________________________________ sub PrintJavaMainPage { print <<"EOM"; EOM } # ________________________________________________________________________ sub PrintCustomizePage { my $graph_options = ''; foreach $OptionCode (sort keys %GraphOptions) { $graph_options .= <<"EOM";See Also:
"; last; } } print <<"EOM";Getting Started: Instructions for Tagging HTML Pages
Currently, your visits ARE NOT being logged. This is the recommended state. To begin logging yourself again, click here: Log My Visits.
EOM } else { $webmaster_logging = <<"EOM";Currently, your visits are being logged. To stop logging yourself (recommended), click here: Do Not Log My Visits.
EOM } print &SetDefaults(<<"EOM", \%PREF);
Webmaster Logging
$webmaster_loggingThis feature requires that you have cookies enabled. Selecting Do Not Log My Visits will set a cookie to your browser that tells the ax.pl script to not log your visits. You will need to do this for each browser you use, and you will need to repeat this process every time you delete cookies.
|
END_OF_HTML } # ________________________________________________________________________ sub DatabaseTimeDescription { return <<"END_OF_HTML";Below is a flow chart of your visitors. Visits are shown with newer hits at the top, and older hits towards the bottom, with timestamps taken from the time of first visit. Successive visits by the same user are grouped together, so that you can view the path taken through your site.
The time interval between hits is given in Hour:Minute:Second format, followed by the number of days, if any.
Note that in most cases, the same individual will have different IP addresses with each network logon. Alternately, the same IP address may represent different visitors over time. Sampling a smaller number of hits over a shorter time period reduces the probability of these errors occuring.
END_OF_HTML } # ________________________________________________________________________ =item GraphSummary Usage: print &GraphSummary(); Dependencies: $const{'truncated_keys'} =cut sub GraphSummary { $relevant_hits = &AddCommas($relevant_hits); $NumGraphLines = &AddCommas($NumGraphLines); $SummaryText = "Each hit below is listed in the order it was counted, with the most recent hits listed first.
Summary:
END_OF_HTML #0013 - end changes return $SummaryText; } #----------------------------------------------------------------------- sub JavaLib { return <<'END_OF_HTML'; END_OF_HTML } #----------------------------------------------------------------------- %FORM = (); &WebFormL( \%FORM ); my $b_is_login = 0; $err = ''; Err: { if ($FORM{'SetCookie'}) { $hostname = $ENV{'HTTP_HOST'} || $ENV{'SERVER_NAME'}; $hostname = lc($2) if ($hostname =~ m!^([^\.]+)(.*)$!); print "Set-Cookie: axs_no_log=$FORM{'CookieValue'}; expires=Thu, 24-Sep-2020 20:58:18 GMT; domain=$hostname; path=/\015\012"; print "Content-Type: text/html\015\012\015\012"; print ""; last Err; } print "Pragma: no-cache\015\012"; print "Content-Type: text/html\015\012\015\012"; if ($0 =~ m!^(.*)(\\|/)!) { unless (chdir($1)) { $err = "unable to chdir to local script folder '$1' - $!"; next Err; } print "\015\012"; } $const{'is_demo'} = (-e 'is_demo') ? 1 : 0; # Build generic timestamp for all functions: @MyT = localtime(time); # The following guesses the script address when $ENV is undefined, which # happens during command-line mode: unless ($This_Script_Address) { $This_Script_Address = ''; $This_Script_Address = $1 if ($0 =~ m!([^\\|\/]+)$!); } print &Header; if (($AllowDebug) && (&query_env('QUERY_STRING') =~ m!^debugme$!i)) { &PrintDebugInfo(1); last Err; } $FilterString = $FORM{'Filter'} || ''; #changed 0022 $err = &check_regex($FilterString); next Err if ($err); ($err, $b_is_login, %PREF) = &AuthPref($prefs); next Err if ($err); last Err unless ($b_is_login); if ($FORM{'Target'} && ($FORM{'Target'} eq 'LogOut')) { print &Authenticate; $b_is_login = 0; last Err; } $err = &check_regex($PREF{'My_Web_Address'}); next Err if ($err); # Next, we open the log file and import all the records. This is *only* # done if we're going to make graphs this time: if ($FORM{'show_data'} || $FORM{'MakeGraphs'} || $FORM{'terminate'}) { print "\r\n"; # Allows the "L" flag to date-filter database results (for reverse # compatibility): if ($FORM{'show_data'} && ($FORM{'maximum'} !~ m!^\d*$!)) { $FORM{'since_last'} = 'on'; } # If date filtering is enabled, the dates are converted into a format # that makes sense to AXS: ($StartNumber,$StartString,$EndNumber,$EndString) = &FormatDates($FORM{'start_date'}, $FORM{'end_date'}, $FORM{'recent'}, $FORM{'since_last'}, $PREF{'last_number'}); # Open the log file and store all of the hits in the # @LINES array. Run whichever filters are necessary, for date/time # or by-file filtering. This preps @LINES and also $total_hits. unless (open(LOGFILE,"<$LogFile")) { &PrintDebugInfo(0); last Err; } binmode(LOGFILE); if ($FilterString eq '') { $FILTER = '(\|[^\|]*){10,10}\|(\d*)\|\d*\|(\d*)'; } elsif ($FilterString =~ m!^host:(.*)$!i) { $FILTER = '\|[^\|]*'.$1.'[^\|]*(\|[^\|]*){9,9}\|(\d*)\|\d*\|(\d*)'; } elsif ($FilterString =~ m!^ip:(.*)$!i) { $FILTER = '\|[^\|]*\|[^\|]*'.$1.'[^\|]*(\|[^\|]*){8,8}\|(\d*)\|\d*\|(\d*)'; } elsif ($FilterString =~ m!^from:(.*)$!i) { $FILTER = '\|[^\|]*\|[^\|]*\|[^\|]*'.$1.'[^\|]*(\|[^\|]*){7,7}\|(\d*)\|\d*\|(\d*)'; } elsif ($FilterString =~ m!^to:(.*)$!i) { $FILTER = '\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*'.$1.'[^\|]*(\|[^\|]*){6,6}\|(\d*)\|\d*\|(\d*)'; } elsif ($FilterString =~ m!^browser:(.*)$!i) { $FILTER = '\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*'.$1.'[^\|]*(\|[^\|]*){5,5}\|(\d*)\|\d*\|(\d*)'; } elsif ($FilterString) { $FILTER = '.*'.$FilterString.'(.*)\|(\d*)\|\d*\|(\d*)\|(export\|)?\r?$'; } else { $FILTER = '(\|[^\|]*){10,10}\|(\d*)\|\d*\|(\d*)'; } #print "\r\n"; $total_hits = 0; if ($StartNumber || $EndNumber || $FilterString) { $EndSearchNow = 0; while (defined($_ =There were $total_hits total hits analyzed"; if ($total_corrupt_rows) { $SummaryText .= " ($total_corrupt_rows data points were corrupt)"; } $SummaryText .= ". Of these, $relevant_hits were "; if ($NumGraphLines) { $SummaryText .= "relevant, and they resulted in $NumGraphLines lines in the table. " } else { $SummaryText .= 'relevant. '; } if (!$FilterString) { $SummaryText .= "No string matching was done against the access log. "; } elsif ($FilterString =~ m!^host:(.*)$!i) { $SummaryText .= "Searched only hits whose hostname matched \"" . html_encode($1) . "\". "; } elsif ($FilterString =~ m!^ip:(.*)$!i) { $SummaryText .= "Searched only hits whose IP address matched \"" . html_encode($1) . "\". "; } elsif ($FilterString =~ m!^from:(.*)$!i) { $SummaryText .= "Searched only hits whose referers matched \"" . html_encode($1) . "\". "; } elsif ($FilterString =~ m!^to:(.*)$!i) { $SummaryText .= "Searched only hits in which the document hit matched \"" . html_encode($1) . "\". "; } elsif ($FilterString =~ m!^browser:(.*)$!i) { $SummaryText .= "Searched only hits in which the browser name matched \"" . html_encode($1) . "\". "; } else { $SummaryText .= "Searched only records whose text matched \"" . html_encode($FilterString) . "\". "; } if (($StartString) && ($EndString)) { $SummaryText .= "Restricted to hits occurring between $StartString, and $EndString.
"; } elsif ($StartString) { $SummaryText .= "Restricted to hits occurring on or after $StartString."; } elsif ($EndString) { $SummaryText .= "Restricted to hits occurring on or before $EndString."; } else { $SummaryText .= "The log was not filtered by date."; } if ($const{'truncated_keys'}) { $SummaryText .= "$const{'truncated_keys'} of the text keys were longer than $PREF{'MaxChars'} characters, and were truncated in the display. This behavior can be controlled with the \"maximum displayed characters\" setting on the Customize page.
\n"; } #0013 - added descriptive sentence about how local web pages are defined $SummaryText .= <<"END_OF_HTML";Local web pages are those whose URL contains the substring "$PREF{'My_Web_Address'}". All other documents are considered remote web pages.
Error: $err.
\n"; } &Footer($b_is_login); # This is the end - everything below is a sub-procedure called above. # ________________________________________________________________________ # Prints a line of the graph: # # Format is &print_line(Name,Value) where Name is something # like 'Netscape 3' and Value is the number of hits. #| ' . html_encode($graph_name) . ': | Hits: | Graph: | |
|---|---|---|---|
| No matches found for your search. Sorry. | |||
| Day of Year: | Hits: | Graph: | |
|---|---|---|---|
| Day of Week: | Hits: | Graph: | |
|---|---|---|---|
| Hour of Day: | Hits: | Graph: | ||
|---|---|---|---|---|
| '; if ($PREF{'UseMilTime'}) { print "$_:00"; } else { if ($_ == 0) { print 'Midnight'; } elsif ($_ < 12) { print $_.' AM'; } elsif ($_ == 12) { print 'High noon'; } else { print $_ - 12; print ' PM'; } } print ' | '; $V = $HourCount[$_]; print sprintf("%.2f",($V * $RH100)); print '% | '; if ($V) { print "$V | "; # traps minimum width at 1, since width=0 is ignored by browser: $width = int($multiplier * $V) || 1; print "'; } print ' | |
The average number of documents viewed per visitor is $avg_docs_per_visitor.EOM print &GraphSummary; $graph_made++; } sub PrettyTime { ($Hour,$Minutes,$Seconds) = @_; #changed 0013 - fixed problems with date rendering $Minutes = reverse(substr(reverse("00$Minutes"), 0, 2)); $Seconds = reverse(substr(reverse("00$Seconds"), 0, 2)); if ($PREF{'UseMilTime'}) { $Hour = reverse(substr(reverse(" $Hour"), 0, 2)); return "$Hour:$Minutes:$Seconds"; } elsif ($Hour < 12) { $Hour = reverse(substr(reverse(" $Hour"), 0, 2)); return "$Hour:$Minutes:$Seconds AM"; } else { $Hour -= 12; $Hour = reverse(substr(reverse(" $Hour"), 0, 2)); return "$Hour:$Minutes:$Seconds PM"; } #end changes } # Begin Show Database Procedure: sub show_data { if ($FORM{'maximum'} =~ /\d+/) { $array_size = scalar @LINES; if ($FORM{'maximum'} < $array_size) { splice(@LINES,0,$array_size - $FORM{'maximum'}); } } print &DatabaseTimeDescription; print '
There have been a total of $ac_internal_hits on local documents from $unique_ip_count unique IP addresses.
';
($relevant_hits,$NumGraphLines) = (0,0);
foreach (reverse @LINES) {
$relevant_hits++;
($VisitHost,$IPAddress,$T3,$T4,$Browser,$SS,$MM,$HH,$Day,$T10,$Year,$T12,$Redirect) = (split(/\|/,$_))[1..12,14];
$Referer = $T3 ? &url_format($T3) : '';
$WebPage = &url_format($T4);
$HourMinSec = &PrettyTime($HH,$MM,$SS);
$WeekDay = $LongWeekDays[$T12];
$Month = $LongMonths[$T10];
$Year += 1900;
$Redirect = ($Redirect eq 'export') ? 1 : 0;
#changed 0015 - security fix
foreach ($VisitHost, $IPAddress, $Browser) {
$_ = html_encode($_); #changed 0015 - security fix
}
print "A visitor from $VisitHost ($IPAddress)\n";
if (($Redirect) && ($Referer ne $WebPage)) {
print "was redirected to $WebPage\n";
print "from $Referer\n";
}
elsif ($Redirect) {
print "visited $WebPage\n";
}
else {
if ($Referer) {
print "arrived from $Referer,\n";
}
else {
print "arrived without a refering URL,\n";
}
print "and visited $WebPage\n";
}
print "at $HourMinSec on $WeekDay, $Month $Day, $Year.\n";
print "This visitor used $Browser.\n";
print "\n";
}
print '';
print &GraphSummary;
$graph_made++;
} # End Show Database Procedure.
# Begin Show Database-Sytle Visitor Flow:
sub show_data_flow {
if ($FORM{'maximum'} =~ /\d+/) {
$array_size = @LINES;
if ($FORM{'maximum'} < $array_size) {
splice(@LINES,0,$array_size - $FORM{'maximum'});
}
}
($total_ips,$multiple_hit_ips) = (0,0);
$delimiter = 'Flow_Chart_Delimiter';
foreach (@LINES) {
next unless (m!^\|([^\|]+)\|([^\|]+)!);
if ($IPFLOW{$2}) {
$IPFLOW{$2} .= $delimiter.$_;
}
else {
push(@IPS,$2);
$IPFLOW{$2} = $_;
$total_ips++;
}
}
print &DatabaseFlowDescription;
print '';
foreach $key (reverse @IPS) {
@LINES = split(/$delimiter/,$IPFLOW{$key});
$num_hits = scalar @LINES;
if (($num_hits > 1) || ($FORM{'format'} eq 'Sort All by Visitor')) {
# Multiple documents visited; generate flow chart:
$multiple_hit_ips++ if ($num_hits > 1);
@terms = split(/\|/,$LINES[0]);
$HourMinSec = &PrettyTime($terms[8],$terms[7],$terms[6]);
if ($num_hits > 2) {
$NumTimes = "$num_hits times";
}
elsif ($num_hits == 1) {
$NumTimes = 'once';
}
else {
$NumTimes = 'twice';
}
#changed 0015 - security fix
foreach ($terms[1], $terms[2], $terms[3], $terms[4], $terms[5]) {
$_ = html_encode($_); #changed 0015 - security fix
}
$FullYear = 1900 + $terms[11];
print <<"EOM";
A visitor from $terms[1] ($terms[2]) was logged $NumTimes,
starting at $HourMinSec on $LongWeekDays[$terms[12]], $LongMonths[$terms[10]] $terms[9], $FullYear.
The initial browser was $terms[5].
EOM
print ' This visitor first ';
$first = 'true';
foreach (@LINES) {
@terms = split(/\|/,$_);
if ($first ne 'true') {
$ThisTime = ((((($terms[13] * 24) + $terms[8]) * 60) + $terms[7]) * 60) + $terms[6];
# $INT is the time interval in seconds:
$INT = ($ThisTime - $PrevTime);
#changed 0013 - fixed date rendering problem
$seconds = int($INT % 60);
$minutes = int(($INT % 3600) / 60);
$hours = int(($INT % 86400) / 3600);
$minutes = reverse(substr(reverse("00$minutes"), 0, 2));
$seconds = reverse(substr(reverse("00$seconds"), 0, 2));
$hours = reverse(substr(reverse("00$hours"), 0, 2));
#end changes
print " $hours:$minutes:$seconds";
if ($days = int($INT/86400)) {
print " and $days day";
print 's' if ($days > 1);
}
print " later, ";
}
if (($terms[14] eq 'export') && ($terms[3] ne $terms[4])) {
print "was redirected to " . &url_format($terms[4]) . "\n";
print " from " . &url_format($terms[3]) . "\n\n";
}
elsif ($terms[14] eq 'export') { # Image redirect
print "dropped by " . &url_format($terms[3]) . "\n\n";
}
else {
if ($terms[3]) {
print "arrived from " . &url_format($terms[3]) . "\n";
}
else {
print "arrived without a refering URL,\n";
}
print " and visited " . &url_format($terms[4]) . "\n";
print "\n";
}
$first = 'false';
$PrevTime = ((((($terms[13] * 24) + $terms[8]) * 60) + $terms[7]) * 60) + $terms[6];
} # End foreach hit per IP.
} # End test of more than one hit per IP.
} # End foreach loop through all IP's.
print <<"EOM";
Summary:
There were visits from $total_ips distinct IP addresses. However, only $multiple_hit_ips of these visited more than one document.
EOM $graph_made++; } # End Show Database-Style Visitor Flow. # Begin Export/Delete Log Procedure: sub kill_it { my $err = ''; Err: { $graph_made++; if ($const{'is_demo'}) { $err = "the deletion of the access log is not allowed in the online demo"; next Err; } unless (open(NEWLOG,">$LogFile")) { $err = "unable to open log file '$LogFile' for writing - $!"; next Err; } binmode(NEWLOG); if ($StartNumber) { $NumLogEntries = scalar @LINES; foreach (@LINES) { print NEWLOG; } } close(NEWLOG); $NewLogSize = -s $LogFile; print <<"EOM";Access Log Deleted:
EOM last Err; } continue { print "The log file has been successfully deleted.
EOM print <<"EOM" if ($StartNumber);Hits since $StartString were retained. There are now $NumLogEntries entries in the access log. The new log size is $NewLogSize bytes.
EOM print <<"EOM";
Error: $err.
\n"; } } # This is the routine to support the new "Browser Wars" report. # The routine for the "Abbreviated Browser" report has been renamed get_browser_ver sub get_browser_name { local $_ = shift; return 'Unknown/Other' unless ($_); # I reformatted the code below to make it appear more tabular and easier to read. # You may have to clean up the tabs on some lines. # I found that my email and text editors don't match. if (m!Opera.(\d)!i) { return 'Opera'; } elsif (m!Mozilla/(\d)!i) { if (m!compatible!i) { if (m!WebTV!i) { return 'WebTV'; } elsif (m!AOL!i) { return 'AOL\'s Browser'; } elsif (m!MSIE!i) { return 'Internet Explorer'; } elsif (m!iCab!i) { return 'iCab'; } elsif (m!Mozilla/3.01.\(compatible;?\)!) { return 'Cache/Proxy server'; } elsif (m!Powermarks!i) { return 'Powermarks bookmark thing'; } elsif (m!FDSE.robot!i) { return 'Spider/Crawler'; } elsif (m!NetMind-Minder!i) { return 'Spider/Crawler'; } elsif (m!BorderManager!i) { return 'Cache/Proxy server'; } else { return 'Unknown/Other'; } } else { return 'Netscape'; } } elsif (m!(Microsoft Internet Explorer)|(MSIE)!i) { return 'Internet Explorer'; } elsif (m!MSProxy!i) { return 'Cache/Proxy server'; } elsif (m!(Crawler)|(Spider)|(Scooter)|(bot)!i) { return 'Spider/Crawler'; } elsif (m!(IWENG)|(aolbrowser)!i) { return 'AOL\'s Browser'; } elsif (m!Lynx!i) { return 'Lynx'; } elsif (m!WebExplorer!i) { return 'IBM WebExplorer'; } elsif (m!QuarterDeck!i) { return 'QuarterDeck Mosaic'; } elsif (m!SPRY!i) { return 'Compuserve\'s SPRY Mosaic'; } elsif (m!Enhanced_Mosaic!i) { return 'NCSA Mosaic (Enhanced)'; } elsif (m!Mosaic!i) { return 'NCSA Mosaic'; } elsif (m!PRODIGY!i) { return 'Prodigy\'s Browser'; } else { return 'Unknown/Other'; } } # end sub get_browser_name # This is the routine to support the old "Abbreviated Browser" report. # It has been renamed from get_browser_name sub get_browser_ver { local $_ = shift; return 'Unknown/Other' unless ($_); if (m!Opera.(\d)!i) { return "Opera v$1.x"; } elsif (m!Mozilla/(\d)!i) { if (m!compatible!i) { if (m!WebTV!i) { return 'WebTV'; } elsif (m!AOL (\d).(\d)!i) { return "AOL's Browser v$1.$2"; } elsif (m!AOL-IWENG (\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!MSIE.?(\d).(\d)!i) { return "Internet Explorer v$1.$2"; } elsif (m!iCab (\d).(\d)!i) { return "iCab v$1.$2"; } elsif (m!Konqueror!i) { return 'Konqueror'; } elsif (m!Powermarks!i) { return 'Powermarks bookmark thing'; } elsif (m!Mozilla/3.01.\(compatible;?\)!) { return 'Cache/Proxy server (Unknown/Other)'; } elsif (m!BorderManager!i) { return 'Cache/Proxy server (Border Manager)'; } elsif (m!FDSE.robot!i) { return 'Spider/Crawler (FDSE)'; } elsif (m!NetMind-Minder!i) { return 'Spider/Crawler (NetMind)'; } elsif (m!openfind!i) { return 'Spider/Crawler (Openfind)'; } elsif (m!WebWasher!i) { return 'Spider/Crawler (WebWasher)'; } elsif (m!WISEnutbot!i) { return 'Spider/Crawler (WISEnut)'; } elsif (m!WebWasher!i) { return 'Spider/Crawler (WebWasher)'; } else { return 'Unknown/Other'; } } elsif (m!Mozilla/(\d).(\d)!i) { my $nsver = $1; if ($nsver >= 5) { $nsver++; } return "Netscape v$nsver.$2"; } else { return "Netscape v$1.x"; } } elsif (m!Microsoft Internet Explorer/(\d)!i) { return "Internet Explorer v$1.x"; } elsif (m!MSIE/(\d)!i) { return "Internet Explorer v$1.x"; } elsif (m!MSProxy!i) { return 'Cache/Proxy server (MSProxy)'; } elsif (m!FAST-WebCrawler!i) { return 'Spider/Crawler (AllTheWeb)'; } elsif (m!Scooter!i) { return 'Spider/Crawler (Altavista)'; } elsif (m!Ask Jeeves!i) { return 'Spider/Crawler (Ask Jeeves)'; } elsif (m!Googlebot!i) { return 'Spider/Crawler (Google)'; } elsif (m!(Crawler)|(Spider)|(bot)!i) { return 'Spider/Crawler (Unknown/Other)'; } elsif (m!Teleport Pro!i) { return 'Teleport Pro Offline Browser'; } elsif (m!IWENG/(\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!aolbrowser/(\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!Lynx!i) { return 'Lynx'; } elsif (m!WebExplorer!i) { return 'IBM WebExplorer'; } elsif (m!QuarterDeck!i) { return 'QuarterDeck Mosaic'; } elsif (m!SPRY!i) { return 'Compuserve\'s SPRY Mosaic'; } elsif (m!Enhanced_Mosaic!i) { return 'NCSA Mosaic (Enhanced)'; } elsif (m!Mosaic!i) { return 'NCSA Mosaic'; } elsif (m!PRODIGY!i) { return 'Prodigy\'s Browser'; } else { return 'Unknown/Other'; } } # end sub get_browser_ver sub get_os_type { local($_) = shift; return 'Unknown Platform' unless $_; if (m!(win95)|(windows 95)!oi) { return 'Windows 95'; } elsif (m!(win 9x 4.9|windows millennium)!oi) { return 'Windows ME'; } elsif (m!(win98)|(windows 98)!oi) { return 'Windows 98'; } elsif (m!Windows NT 5!i) { return 'Windows 2000'; } # 2 lines below will show different versions of NT # I think this is not useful because 3.5 is very rare and so many are unknown #elsif (m!(Windows NT 4)|(winNT ?4)!oi) { return 'Windows NT 4'; } #elsif (m!(Windows NT 3)|(winNT ?3)!oi) { return 'Windows NT 3.5'; } # The following line catches the remaining NT entries without a version, which is most of them elsif (m!(Windows NT)|(winNT)!oi) { return 'Windows NT'; } elsif (m!win16!oi) { return 'Windows 16-bit'; } elsif (m!win32!oi) { return 'Windows 32-bit'; } elsif (m!Windows 3.1!oi) { return 'Windows 3.1'; } elsif (m!Windows!oi) { if (m!32bit!oi) { return 'Windows 32-bit'; } else { return 'Windows 16-bit'; } } elsif (m!Window!oi) { return 'X Windows'; } elsif (m!Mac!oi) { if (m!(PPC)|(PowerPC)!oi) { return 'Macintosh (PowerPC)'; } else { return 'Macintosh (68K)'; } } elsif (m!FreeBSD!oi) { return 'UNIX (FreeBSD)'; } elsif (m!HP-UX!oi) { return 'UNIX (HP-UX)'; } elsif (m!Linux!oi) { return 'UNIX (Linux)'; } elsif (m!SunOS!oi) { return 'UNIX (SunOS)'; } elsif (m!(X11)|(Lynx)!oi) { return 'UNIX (Unknown/Other)'; } elsif (m!Amiga!oi) { return 'Amiga'; } elsif (m!OS/2!oi) { return 'OS/2'; } elsif (m!IWENG!oi) { return 'Windows 16-bit'; } elsif (m!WebTV!oi) { return 'WebTV'; } else { return 'Unknown Platform'; } } # end sub get_os_type sub get_browser_name_OLD { local $_ = shift; return 'Other Agents' unless ($_); if (m!Mozilla/(\d)!i) { if (m!compatible!i) { if (m!WebTV!i) { return 'WebTV'; } elsif (m!AOL.(\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!AOL-IWENG (\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!MSIE.(\d)!i) { return "MSIE v$1.x"; } elsif (m!Opera!i) { return 'Opera'; } elsif (m!Mozilla/3.01.\(compatible;?\)!) { return 'Cache/Proxy server'; } elsif (m!Powermarks!i) { return 'Powermarks bookmark thing'; } elsif (m!FDSE.robot!i) { return 'FDSE robot'; } elsif (m!NetMind-Minder!i) { return 'NetMind-Minder'; } elsif (m!BorderManager!i) { return 'Border Manager'; } else { return 'Other Agents'; } } elsif (m!Mozilla/4.(\d)!i) { return "Netscape v4.$1"; } else { return "Netscape v$1.x"; } } elsif (m!Microsoft Internet Explorer/(\d)!i) { return "MSIE v$1.x"; } elsif (m!IWENG/(\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!aolbrowser/(\d)!i) { return "AOL's Browser v$1.x"; } elsif (m!Lynx!i) { return 'Lynx'; } elsif (m!WebExplorer!i) { return 'IBM WebExplorer'; } elsif (m!QuarterDeck!i) { return 'QuarterDeck Mosaic'; } elsif (m!SPRY!i) { return 'Compuserve\'s SPRY Mosaic'; } elsif (m!Enhanced_Mosaic!i) { return 'NCSA Mosaic (Enhanced)'; } elsif (m!Mosaic!i) { return 'NCSA Mosaic'; } elsif (m!PRODIGY!i) { return 'Prodigy\'s Browser'; } else { return 'Other Agents'; } } sub get_os_type_OLD { # this guy needs some work: check for NT 3.51/4.0/5.0; check for Linux # versus Unix or whatever; make sure Netscape returns Windows 98 instead # of Windows 95. local($_) = shift; return 'Unknown Platform' unless $_; if (m!(win95)|(windows 95)!oi) { return 'Windows 95'; } #changed 0016 elsif (m!(win 9x 4.9|windows millennium)!oi) { return 'Windows ME'; } elsif (m!(win98)|(windows 98)!oi) { return 'Windows 98'; } elsif (m!Windows NT 5!i) { return 'Windows 2000'; } elsif (m!(winNT)|(Windows NT)!oi) { return 'Windows NT'; } elsif (m!win16!oi) { return 'Windows 16-bit'; } elsif (m!win32!oi) { return 'Windows 32-bit'; } elsif (m!Windows 3.1!oi) { return 'Windows 3.1'; } elsif (m!Windows!oi) { if (m!32bit!oi) { return 'Windows 32-bit'; } else { return 'Windows 16-bit'; } } elsif (m!Window!oi) { return 'X Windows'; } elsif (m!Mac!oi) { if (m!PPC!oi) { return 'Macintosh (PowerPC)'; } elsif (m!PowerPC!oi) { return 'Macintosh (PowerPC)'; } else { return 'Macintosh (68K)'; } } elsif (m!Amiga!oi) { return 'Amiga'; } elsif (m!OS/2!oi) { return 'OS/2'; } elsif (m!X11!oi) { if (m!HP-UX!oi) { return 'UNIX (HP-UX)'; } elsif (m!Linux!oi) { return 'UNIX (Linux)'; } elsif (m!SunOS!oi) { return 'UNIX (SunOS)'; } else { return 'UNIX (Other/Unspecified)'; } } elsif (m!IWENG!oi) { return 'Windows 16-bit'; } elsif (m!Lynx!oi) { return 'UNIX (Other/Unspecified)'; } elsif (m!WebTV!oi) { return 'WebTV'; } else { return 'Unknown Platform'; } } sub quickparse { my ($str) = @_; my %hash = (); my $pair = ''; foreach $pair (split(m!\&!s, $str)) { next unless ($pair =~ m!^(.*?)=(.*)$!s); $hash{$1} = &url_decode($2); } return %hash; } sub url_format { # URL Format takes a URL and turns it into a hyperlink with an # abbreviated (no "http://") viewable output. Links from Altavista # and other search engines are formatted logically: local($_) = shift; if ((m!$PREF{'My_Web_Address'}!i) && (m!http://(.*)!i)) { # Use %LocalAddressTitlePairs if it exists: if ($UseLocalAddressTitlePairs == 1) { foreach $Address (keys %LocalAddressTitlePairs) { return "$LocalAddressTitlePairs{$_}" if (m!^$Address$!i); } } return $1; } my %hash = (); my ($linktext, $trailtext) = ($_, ''); if (($_ !~ /\?/) && (m!http://(.*)!i)) { $linktext = $1; } elsif ($_ !~ m!\?!) { #def } elsif (m!://([^/]+)\.google\.([^/]+)/\w+\?(.*)$!i) { ($host, $tld, $data) = ($1, $2, $3); %hash = &quickparse( $data ); $start = $hash{'start'} || 0; $terms = $hash{'q'} || $hash{'as_q'} || 'unknown'; if ($hash{'num'}) { $end = $start + $hash{'num'}; } else { $end = $start + 10; } $start++; ($linktext, $trailtext) = ( "$host.google.$tld", "$terms $start-$end" ); } elsif (/\:\/\/([^\/]*)altavista\.([^\/|\?]*)(.*)\?.*q\=([^\&]+).*stq\=(\d+)/i) { ($Host,$Domain,$Terms,$Rank) = ($1,$2,&url_decode($4),$5); ($linktext, $trailtext) = ("$Host.altavista.$Domain", "$Terms ".($Rank+1).'-'.($Rank+10) ); } elsif (/\:\/\/([^\/]*)altavista\.([^\/|\?]*)(.*)\?.*q=([^\&]+).*navig(\d+)?/i) { ($Host,$Domain,$Terms,$Rank) = ($1,$2,&url_decode($4),($5?$5:0)); ($linktext, $trailtext) = ("$Host.altavista.$Domain", "$Terms ".($Rank+1).'-'.($Rank+10) ); } elsif (/\:\/\/([^\/]*)altavista\.([^\/|\?]*)(.*)\?.*q\=([^\&]+)/i) { ($Host,$Domain,$Terms) = ($1,$2,&url_decode($4)); ($linktext, $trailtext) = ("$Host.altavista.$Domain", "$Terms 1-10" ); } elsif (/\:\/\/([^\/]*)webcrawler\.([^\/]+)(.*)\?(s|search|searchText)\=([^\&]+).*\&start\=(\d+).*perPage\=(\d+)/i) { ($Host,$Domain,$Terms,$Rank,$Increment) = ($1,$2,&url_decode($5),$6,$7); ($linktext, $trailtext) = ( "$Host.webcrawler.$Domain" , "$Terms ".($Rank+1)."-".($Rank+$Increment) ); } elsif (/\:\/\/([^\/]*)webcrawler\.([^\/]+).*(s|search|searchText)\=([^\&]+)/i) { ($Host,$Domain,$Terms) = ($1,$2,&url_decode($4)); ($linktext, $trailtext) = ( "$Host.webcrawler.$Domain", "$Terms 1-25" ); } elsif (/\:\/\/([^\/]*)metacrawler\.([^\/]+).*general\=([^\&]+).*start\=(\d+).*rpp\=(\d+)/i) { ($Host,$Domain,$Terms,$Rank,$Increment) = ($1,$2,&url_decode($3),$4,$5); ($linktext, $trailtext) = ( "$Host.metacrawler.$Domain", "$Terms ".($Rank+1)."-".($Rank+$Increment) ); } elsif (/\:\/\/([^\/]*)metacrawler\.([^\/]+).*general\=([^\&]+)/i) { ($Host,$Domain,$Terms) = ($1,$2,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.metacrawler.$Domain", "$Terms 1-25" ); } elsif (/\:\/\/([^\/]*)netfind.aol\.([^\/]+).*start=(\d+).*&search=([^\&]+).*start=(\d+).*perPage=(\d+)/i) { ($Host,$Domain,$Terms,$Rank,$Increment) = ($1,$2,&url_decode($5),$4,$6); ($linktext, $trailtext) = ( "$Host.netfind.aol.$Domain", "$Terms ".($Rank+1)."-".($Rank+$Increment) ); } elsif (/\:\/\/([^\/]*)netfind\.aol\.([^\/]+).*search=([^\&]+)/i) { ($Host,$Domain,$Terms) = ($1,$2,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.netfind.aol.$Domain", "$Terms 1-25" ); } elsif (/\:\/\/([^\.]*)\.infoseek\.com(.*)\?.*qt=([^\&]+).*st=(\d+)?/i) { ($Host,$Rank,$Terms) = ($1,$5,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.infoseek.com", "$Terms ".($Rank+1).'-'.($Rank+10) ); } elsif (/\:\/\/([^\.]*)\.infoseek\.com(.*)\?.*qt=([^\&]+)/i) { ($Host,$Terms) = ($1,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.infoseek.com", "$Terms 1-10" ); } elsif (/\:\/\/([^\.]*)\.infoseek\.com(.*)\?.*oq=([^\&]+).*(st=)?(\d+)?/i) { ($Host,$Rank,$Terms) = ($1,$5,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.infoseek.com", "$Terms ".($Rank+1).'-'.($Rank+10) ); } elsif (/\:\/\/([^\.]*)\.infoseek\.com(.*)\?.*oq=([^\&]+).*(st=)?(\d+)?/i) { ($Host,$Terms) = ($1,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.infoseek.com", "$Terms 1-10" ); } elsif (/\:\/\/([^\.]*)\.excite\.com(.*)\?(.*)/i) { ($Host,$rank,$Increment) = ($1,0,10); @parts = split(/\&/,$3); foreach $part (@parts) { if ($part =~ /^search=(.*)/) { $terms = $1; $terms =~ tr/+/ /; $terms =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C',hex($1))/eg; } if ($part =~ /^perPage=(.*)/) { $Increment = $1; } if ($part =~ /^start=(.*)/) { $rank = ($1 + $Increment); } } ($linktext, $trailtext) = ( "$Host.excite.com", "$terms " . ($rank + 1) . "-" . ($rank + $Increment) ); } elsif (m!://([^\/]*)\.yahoo\.([^\/]*).*\?.*p=([^\&]+).*b=(\d+)!i) { ($Host,$Domain,$Terms,$Rank) = ($1,$2,&url_decode($3),$4); ($linktext, $trailtext) = ( "$Host.yahoo.$Domain", "$Terms ".$Rank.'-'.($Rank + 19) ); } elsif (m!://([^\/]*)\.yahoo\.([^\/]*).*\?.*p=([^\&]+)!i) { ($Host,$Domain,$Terms) = ($1,$2,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.yahoo.$Domain", "$Terms 1-20" ); } elsif (/\:\/\/([^\/]*)\.hotbot\.([^\/]*).*\?.*MT=([^\&]+).*base=(\d+)/i) { ($Host,$Domain,$Terms,$Rank,$NextRank) = ($1,$2,&url_decode($3),($4+11),($4+20)); ($linktext, $trailtext) = ( "$Host.hotbot.$Domain", "$Terms $Rank-$NextRank" ); } elsif (/\:\/\/([^\/]*)\.hotbot\.([^\/]*).*\?.*MT=([^\&]+)/i) { ($Host,$Domain,$Terms) = ($1,$2,&url_decode($3)); ($linktext, $trailtext) = ( "$Host.hotbot.$Domain", "$Terms 1-10" ); } elsif (/http\:\/\/(.*)/i) { $linktext = $1; } if (($PREF{'MaxChars'}) and (length($linktext) > $PREF{'MaxChars'})) { $linktext = substr( $linktext, 0, $PREF{'MaxChars'} ); $const{'truncated_keys'}++; } if ($trailtext) { if (($PREF{'MaxChars'}) and (length($trailtext) > $PREF{'MaxChars'})) { $trailtext = substr( $trailtext, 0, $PREF{'MaxChars'} ); $const{'truncated_keys'}++; } return '' . $linktext . ' ' . $trailtext . ''; } else { return '' . $linktext . ''; } } # End url_format procedure. =item AuthPref Usage: ($err, $b_is_login, %PREF) = &AuthPref( $prefs_file ); =cut sub AuthPref { my ($PrefsFile) = @_; my $b_is_login = 0; my $err = ''; Err: { local $_; # Try to open the prefs file: unless (open(PREF, "<$PrefsFile")) { $err = "unable to open file '$PrefsFile' for reading - $!"; next Err; } binmode(PREF); # Initialize $PREF{'format'} and {'maximum'} %PREF = ( 'format', '', 'maximum', '', 'end_date', '', 'start_date', '', 'since_last', '', 'last_number', '', 'last_number_temp', '', 'AuthIP', '', 'last_string', '', 'MaxWidth', 400, 'MaxChars', 128, 'My_Web_Address' => &query_env('HTTP_HOST'), 'images_folder' => 'http://www.xav.com/images/', 'Filter', '', 'recent', '', 'NumSort', 'CHECKED', 'NewWindow', 'CHECKED', 'Highlight', 'CHECKED', 'HideDefaultDoc', 'CHECKED', 'HidePoundSigns','CHECKED', 'UseMilTime', '', ); while (defined($_ =Invalid username or password!
\n"; print "feel free to try again...\n"; } else { print &Authenticate; } last Err; } # User authenticated, continue parsing the preferences. Save them if # necessary: $ThisDayNum = ($MyT[5] * 1000) + $MyT[7] + 1900000; if (($PREF{'last_number_temp'} < $ThisDayNum) || (!$PREF{'last_number'})) { $PREF{'last_number'} = $PREF{'last_number_temp'}; $PREF{'last_string'} = $PREF{'last_string_temp'}; } $PREF{'last_number_temp'} = $ThisDayNum; $PREF{'last_string_temp'} = (&DateByNum((@MyT)[4,3],$MyT[5]+1900))[0]; if ($FORM{'incoming'}) { if ($const{'is_demo'}) { $err = "the saving of preferences has been disabled in the on-line demo"; next Err; } $FORM{'images_folder'} = &Trim($FORM{'images_folder'}); for ('maximum','MaxWidth','MaxChars','My_Web_Address','start_date','end_date','Filter','format', 'images_folder') { $PREF{$_} = $FORM{$_}; delete $FORM{$_}; } for (keys %GraphOptions,'since_last','recent','NumSort','NewWindow','Highlight','HideDefaultDoc','HidePoundSigns', 'UseMilTime') { $PREF{$_} = $FORM{$_} ? 'CHECKED' : ''; delete $FORM{$_}; } } $PREF{'MaxWidth'} = 400 unless ($PREF{'MaxWidth'}); # abbreviated flag for numerical sorting: $NUMS = $PREF{'NumSort'} eq 'CHECKED' ? 1 : 0; # abbreviate bgcolor attribute: if ($PREF{'Highlight'} eq 'CHECKED') { $BGCOLOR = 'BGCOLOR="#dddddd"'; } else { $BGCOLOR = ''; } if ($PREF{'NewWindow'}) { $TARGET = ' TARGET="_blank"'; } else { $TARGET = ''; } if (($ENV{'REMOTE_ADDR'}) and ($ENV{'REMOTE_ADDR'} eq $PREF{'AuthIP'})) { # only write out preferences for authenticated users: unless (open(PREF, ">$prefs")) { $err = "unable to open file '$prefs' for writing - $!"; next Err; } binmode(PREF); foreach $key (sort keys %PREF) { next if (($key eq 'AuthIP') and ($FORM{'Target'}) and ($FORM{'Target'} eq 'LogOut')); print PREF $key.'|'; print PREF $PREF{$key} if ($PREF{$key}); print PREF "|\n"; } close(PREF); } last Err; } return ($err, $b_is_login, %PREF); } sub DateIsValid { ($MM,$DD,$YYYY) = @_; for ($MM,$DD,$YYYY) { return 0 unless m!^\d*$!; } return 0 if (($MM < 1) || ($MM > 12) || ($DD < 1)); if ($YYYY % 4) { return 0 if ($DD > (31,29,31,30,31,30,31,31,30,31,30,31)[$MM-1]); } else { return 0 if ($DD > (31,28,31,30,31,30,31,31,30,31,30,31)[$MM-1]); } return 1; } sub GetYDAY { ($MM,$DD,$YYYY) = @_; if (($YYYY % 4) == 0) { return ((0,31,60,91,121,152,182,213,244,274,305,335)[$MM] + $DD - 1); } else { return ((0,31,59,90,120,151,181,212,243,273,304,334)[$MM] + $DD - 1); } } sub DateByNum { # this is failing for YDAY sometimes. # accepts computer date, returns text string, yday. ($MM, $DD, $YYYY) = @_; # test: # print "\n"; $DD--;$DD++; if ($YYYY < 1000) { if ($YYYY < 50) { $YYYY += 2000; } else { $YYYY += 1900; } } $YDAY = &GetYDAY($MM,$DD,$YYYY); $DaysSince1970 = int(($YYYY-1970)*365.25) + $YDAY + 1; $WeekDay = $LongWeekDays[(localtime($DaysSince1970 * 86400))[6]]; # test: # print "\n"; return ("$LongMonths[$MM] $DD, $YYYY", $YDAY); } sub FormatDates { ($StartInput, $EndInput, $Recent, $SinceLast, $LastNumber) = @_; ($StartNumber, $StartString, $EndNumber, $EndString) = (0,'',0,''); ($MM,$DD,$YYYY) = (0,0,0); MMDDYY: for ($StartInput) { if ($_) { if (m!^\s*(\d{2,2})\D*(\d{2,2})\D*(\d{2,4})?!) { ($MM,$DD,$YYYY) = ($1,$2,($3 ? $3 : $MyT[5])); last MMDDYY if &DateIsValid($MM,$DD,$YYYY); } if (m!^\s*(\d{1,2})\D+(\d{1,2})\D*(\d{2,4})?!) { ($MM,$DD,$YYYY) = ($1,$2,($3?$3:$MyT[5])); last MMDDYY if &DateIsValid($MM,$DD,$YYYY); } LITERAL_MONTH: { if (m!^\s*(\D+)(\d{1,2})\D*(\d{2,4})?!) { ($MonthString,$DD,$YYYY) = ($1,$2,($3?$3:$MyT[5])); } elsif (m!^\s*(\d{1,2})(\D*)(\d{2,4})?!) { ($MonthString,$DD,$YYYY) = ($2,$1,($3?$3:$MyT[5])); } else { last LITERAL_MONTH; } for ($MM=1;$MM<=12;$MM++) { if ($MonthString =~ m!$ShortMonths[$MM-1]!i) { last MMDDYY if &DateIsValid($MM,$DD,$YYYY); last LITERAL_MONTH; } } } for $X (0..6) { if (m!$ShortWeekDays[$X]!i) { ($MM,$DD,$YYYY) = (localtime(time-((7+$MyT[6]-$X)%7)*86400))[4,3,5]; $MM++; last MMDDYY; } } for $X (0..2) { if (m!$ShortDayNames[$X]!i) { ($MM,$DD,$YYYY) = (localtime(time+($X-1)*86400))[4,3,5]; $MM++; last MMDDYY; } } } if ($Recent) { ($MM,$DD,$YYYY) = (localtime((time-86400)))[4,3,5]; $MM++; last MMDDYY; } } # End MMDDYY. if ($MM && $DD && defined($YYYY)) { # kick INT mode, and correct for human->computer month indexing: $MM--; if ($YYYY < 1000) { # User is entering an abbreviated date. Is it 01 for 2001, or 99 for 1999? if ($YYYY < 50) { $YYYY += 2000; } else { $YYYY += 1900; } } ($StartString,$YDAY) = &DateByNum($MM,$DD,$YYYY); $StartNumber = ($YYYY * 1000) + $YDAY; } elsif ($SinceLast) { # or "if $StartInput existed maybe but didn't successfully match anything, and $Recent was not defined, # but $SinceLast is... $StartNumber = $LastNumber; $YYYY = int($LastNumber/1000); $YDAY = $LastNumber % 1000; $DaysSince1970 = int(($YYYY-1970)*365.25) + $YDAY + 1; ($DD,$MM,$YYYY,$WeekDay) = (localtime($DaysSince1970 * 86400))[3..6]; $YYYY += 1900; $WeekDay = $LongWeekDays[$WeekDay]; $StartString = "$WeekDay, $LongMonths[$MM] $DD, $YYYY"; } # Zero out: ($MM,$DD,$YYYY) = (0,0,0); MMDDYY: for ($EndInput) { if ($_) { if (m!^\s*(\d{2,2})\D*(\d{2,2})\D*(\d{2,4})?!) { ($MM,$DD,$YYYY) = ($1,$2,($3?$3:$MyT[5])); last MMDDYY if &DateIsValid($MM,$DD,$YYYY); } if (m!^\s*(\d{1,2})\D+(\d{1,2})\D*(\d{2,4})?!) { ($MM,$DD,$YYYY) = ($1,$2,($3?$3:$MyT[5])); last MMDDYY if &DateIsValid($MM,$DD,$YYYY); } LITERAL_MONTH: { if (m!^\s*(\D+)(\d{1,2})\D*(\d{2,4})?!) { ($MonthString,$DD,$YYYY) = ($1,$2,($3?$3:$MyT[5])); } elsif (m!^\s*(\d{1,2})(\D*)(\d{2,4})?!) { ($MonthString,$DD,$YYYY) = ($2,$1,($3?$3:$MyT[5])); } else { last LITERAL_MONTH; } for ($MM=1;$MM<=12;$MM++) { if ($MonthString =~ m!$ShortMonths[$MM-1]!i) { last MMDDYY if &DateIsValid($MM,$DD,$YYYY); last LITERAL_MONTH; } } } for $X (0..6) { if (m!$ShortWeekDays[$X]!i) { ($MM,$DD,$YYYY) = (localtime(time-((7+$MyT[6]-$X)%7)*86400))[4,3,5]; $MM++; last MMDDYY; } } for $X (0..2) { if (m!$ShortDayNames[$X]!i) { ($MM,$DD,$YYYY) = (localtime(time+($X-1)*86400))[4,3,5]; $MM++; last MMDDYY; } } } if ($Recent || $SinceLast) { ($MM,$DD,$YYYY) = (localtime(time))[4,3,5]; $MM++; last MMDDYY; } } # End MMDDYY. if ($MM && $DD && defined($YYYY)) { # kick INT mode, and correct for human->computer month indexing: $MM--; if ($YYYY < 1000) { # User is entering an abbreviated date. Is it 01 for 2001, or 99 for 1999? if ($YYYY < 50) { $YYYY += 2000; } else { $YYYY += 1900; } } ($EndString,$YDAY) = &DateByNum($MM,$DD,$YYYY); unless ($Recent || $SinceLast) { $EndNumber = ($YYYY * 1000) + $YDAY; } } return ($StartNumber, $StartString, $EndNumber, $EndString); } =item PrintDebugInfo() This runs a filesystem test against $LogFile and dumps a ton of (hopefully) useful information to the screen. =cut sub PrintDebugInfo { my ($verbose) = @_; my $err = ''; Err: { print "Testing log file '$LogFile'...
\n"; if (-e $LogFile) { print "File exists.
\n"; } else { print "Warning: file does not exist.
\n"; } if (open(FILE,">>$LogFile")) { binmode(FILE); close(FILE); print "Success: log file is writable.
\n"; } else { print "Error: unable to write to the log file - $! - $^E.
\n"; print "Resolve this error by creating an empty file named '$LogFile' (if one doesn't already exist) and making it writable.
\n"; } print "Testing preferences file '$prefs'...
\n"; if (-e $prefs) { print "File exists.
\n"; } else { print "Warning: file does not exist.
\n"; } if (open(FILE,">>$prefs")) { binmode(FILE); close(FILE); print "Success: prefs file is writable.
\n"; } else { print "Error: unable to write to the prefs file - $! - $^E.
\n"; print "Resolve this error by creating an empty file named '$prefs' (if one doesn't already exist) and making it writable.
\n"; } unless ($verbose) { print "Vist the debug page for more detailed information.
\n"; last Err; } print <<"EOM";AXS Debug Screen
This is one tool, of many, to help you out. Read the trouble-shooting guide if you need more detailed assistance.
Standard Debugging Information:
| Script Version: | $VERSION |
| Script file: | $0 |
| Perl version: | $] |
| Operating system: | $^O |
Environment Variables:
| " . &html_encode($_) . ": | " . &html_encode(substr($ENV{$_},0,60)) . " |
Assertion Error:
Package: $package
File: $file
Line: $line