# Copyright (c) 1994 Regents of the University of California. # All rights reserved. # $Id: momindex.pl,v 1.9 1994/08/10 10:18:29 fielding Exp $ # --------------------------------------------------------------------------- # momindex: A package for building an index file of metainformation from # the traversal of a World-Wide Web spider. It also keeps track # of traversal results for later summary. # # This software has been developed by Roy Fielding as # part of the Arcadia project at the University of California, Irvine. # # Redistribution and use in source and binary forms are permitted, # subject to the restriction noted below, provided that the above # copyright notice and this paragraph and the following paragraphs are # duplicated in all such forms and that any documentation, advertising # materials, and other materials related to such distribution and use # acknowledge that the software was developed in part by the University of # California, Irvine. The name of the University may not be used to # endorse or promote products derived from this software without # specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' # AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT # LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE. # # Use of this software in any way or in any form, source or binary, # is not allowed in any country which prohibits disclaimers of any # implied warranties of merchantability or fitness for a particular # purpose or any disclaimers of a similar nature. # # IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION # (INCLUDING, BUT NOT LIMITED TO, LOST PROFITS) EVEN IF THE UNIVERSITY # OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # If you have any suggestions, bug reports, fixes, or enhancements, # send them to the author Roy Fielding at . # --------------------------------------------------------------------------- require "www.pl"; require "wwwdates.pl"; require "wwwerror.pl"; require "momconfig.pl"; require "momhistory.pl"; package momindex; # ========================================================================== # Get defaults from momconfig.pl # Temporary file for Index $TempIndex = ($momconfig'TempIndex || "/tmp/mom$$-index.html"); # Standard filename extension for HTML index files (and old version) $Extension = ($momconfig'Extension || 'html'); $OldExtension = ($momconfig'OldExtension || 'old.html'); # ========================================================================== # Status of the indexing process $Active = 0; # Initialize the process summary &init_procsum; # ========================================================================== # ========================================================================== # start(): Start the index file with the basic header information and # the parameters for this particular job. # sub start { local($idxfile, $idxurl, $idxtitle, $chgwin, $expwin) = @_; local($current, $time1, $time2, $replyto, $oldurl); if (defined($chgwin)) { $ChangeDays = $chgwin; $ChangeWindow = $chgwin * 86400; } else { $ChangeDays = $ChangeWindow = 0; } if (defined($expwin)) { $ExpireDays = $expwin; $ExpireWindow = $expwin * 86400; } else { $ExpireDays = $ExpireWindow = 0; } &init_summary; $HasChildren = 0; %BrokenNodes = (); %RedirectNodes = (); %ChangedNodes = (); %ExpiredNodes = (); if ($Active) { print STDERR "Warning: index start occurs before prior index ended\n"; close INDEX; } if (!open(INDEX,"> $TempIndex")) { print STDERR "Unable to open the temporary index file $TempIndex\n"; return 0; } select((select(INDEX), $| = 1)[0]); # Make INDEX unbuffered $current = time; # Get the current date-time stamp $time1 = &wwwdates'wtime($current,''); $time2 = &wwwdates'wtime($current,'GMT'); $replyto = &www'get_def_header('http','From'); print INDEX <<"EOtop"; $idxtitle

$idxtitle

Index started: $time1 ($time2)
by $replyto
EOtop print INDEX "\n
\n"; $Active = 1; # Protect package from misordered calls return 1; } # ========================================================================== # traversed(): Enter an index entry for this document that is being # traversed. # sub traversed { local($node) = @_; local($label, $url, $response, $respmsg, %headers, $current, $lmd, $lmt, $is_broken, $is_redirect, $is_changed, $is_expired, $expd, $expt, $avoided, $untested, $xref, $nextbit); if ($HasChildren) # First, finish off any prior traversal { print INDEX "\n\n"; $HasChildren = 0; } %headers = (); $label = sprintf("momt%04d", $node); $url = &momhistory'get_url($node); $response = &momhistory'recall($node, *headers); $avoided = $untested = 0; $is_broken = $is_redirect = $is_changed = $is_expired = 0; if (&momhistory'was_avoided($node)) { $avoided = 1; $respmsg = "000 Avoided"; } elsif ($response == $wwwerror'RC_not_implemented_client) { $untested = 1; $respmsg = "$wwwerror'RC_not_implemented_client Not Tested"; } else { $respmsg = "$response $wwwerror'RespMessage{$response}"; $is_broken = ($momhistory'WhatToDo{$response} == $momhistory'DO_broken); $is_redirect = ($momhistory'WhatToDo{$response} == $momhistory'DO_redirect); $current = time; $lmd = $headers{'last-modified'}; $is_changed = ($ChangeWindow && defined($lmd) && ($lmt = &wwwdates'get_gmtime($lmd)) && (($lmt + $ChangeWindow) >= $current)); $expd = $headers{'expires'}; $is_expired = ($ExpireWindow && defined($expd) && ($expt = &wwwdates'get_gmtime($expd)) && (($expt - $ExpireWindow) <= $current)); } if ($is_broken) { &save_broken($node, 'Trav', $label, $respmsg, $url); } if ($is_redirect) { &save_redirect($node,'Trav', $label, $respmsg, $url); } if ($is_changed) { &save_changed($node, 'Trav', $label, $respmsg, $url, $lmd); } if ($is_expired) { &save_expired($node, 'Trav', $label, $respmsg, $url, $expd); } $nextbit = ($headers{'title'} || $url); print INDEX "

$nextbit

\n"; if ($is_broken || $is_redirect) { print INDEX ""; } print INDEX $respmsg; if ($is_broken || $is_redirect) { print INDEX ""; } print INDEX "\n\n$url"; if ($nextbit = $headers{'uri'}) { print INDEX "
\nURI: $nextbit"; } if ($lmd) { print INDEX "
\nLast-modified: "; if ($is_changed) { print INDEX ""; } print INDEX $lmd; if ($is_changed) { print INDEX ""; } } if ($expd) { print INDEX "
\nExpires: "; if ($is_expired) { print INDEX ""; } print INDEX $expd; if ($is_expired) { print INDEX ""; } } if ($nextbit = $headers{'reply-to'}) { print INDEX "
\nReply-to: $nextbit"; } print INDEX "\n"; } # ========================================================================== # tested(): Enter an index entry for this node that was just tested. # Note that we do not highlight or save expires dates here. # sub tested { local($node, $labs, $lorig, $ltype, $reused) = @_; local($label, $url, $response, $respmsg, $current, $lmd, $lmt, $nextbit, $is_broken, $is_redirect, $is_changed, $is_indexed, $top, $xref, $untested, $avoided, %headers); if (!$HasChildren) # The first child must start the list { print INDEX "\n"; $HasChildren = 0; } $current = time; # Get the current date-time stamp $time1 = &wwwdates'wtime($current,''); $time2 = &wwwdates'wtime($current,'GMT'); &update_summary; $summary = &get_summary; print INDEX "
\n"; print INDEX "Index ended: $time1 ($time2)\n"; print INDEX "

Summary of Results

\n"; print INDEX "
\n";
    print INDEX $summary;
    print INDEX "
\n"; print INDEX "
\n"; $firstone = 1; print INDEX "

Broken Links

\n"; foreach $node (keys(%BrokenNodes)) { if ($firstone) { print INDEX "\n"; $firstone = 1; } print INDEX "

Redirected Links

\n"; foreach $node (keys(%RedirectNodes)) { if ($firstone) { print INDEX "\n"; $firstone = 1; } if ($ChangeWindow > 0) { print INDEX "

Changed Link Destinations

\n"; foreach $node (keys(%ChangedNodes)) { if ($firstone) { print INDEX "\n"; $firstone = 1; } } if ($ExpireWindow > 0) { print INDEX "

Expired Documents

\n"; foreach $node (keys(%ExpiredNodes)) { if ($firstone) { print INDEX "\n"; $firstone = 1; } } print INDEX "
\n"; print INDEX "
This index was generated by \n"; print INDEX $momconfig'DistInfo; print INDEX "\n
\n"; print INDEX "\n"; close INDEX; $oldname = $idxfile; $oldname =~ s#$Extension$#$OldExtension#o; if ((-e $idxfile) && (!rename($idxfile, $oldname))) { print STDERR "Failed to backup existing $idxfile\n"; } system('mv','-f', $TempIndex, $idxfile); if (!(-e $idxfile)) { print STDERR "Failed to move $TempIndex to $idxfile\n"; } else { chmod 0644, $idxfile; } print "Summary of Results:\n", $summary; $Active = 0; # Protect package from misordered calls } # ========================================================================== # init_procsum(): Initialize the counters used for the Process Summary # sub init_procsum { $ProcTotalHrefs = 0; $ProcHrefsTrav = 0; $ProcHrefsTest = 0; $ProcHrefsAvd = 0; $ProcHrefsUnt = 0; $ProcHrefsBroke = 0; $ProcHrefsRedir = 0; $ProcHrefsChg = 0; $ProcHrefsExp = 0; $ProcHrefsLoc = 0; $ProcNodesTrav = 0; $ProcNodesChg = 0; $ProcNodesExp = 0; $ProcLocalTrav = 0; $ProcLocalChg = 0; $ProcLocalExp = 0; } # ========================================================================== # init_summary(): Initialize the counters used to summarize the results. # sub init_summary { $TotalHrefs = 0; $TotalNodes = 0; $TotalLocal = 0; $TotalRemot = 0; $HrefsTrav = 0; $HrefsTest = 0; $HrefsReus = 0; $HrefsAvd = 0; $HrefsUnt = 0; $HrefsBroke = 0; $HrefsRedir = 0; $HrefsChg = 0; $HrefsExp = 0; $HrefsLoc = 0; $HrefsRmt = 0; $NodesTrav = 0; $NodesTest = 0; $NodesReus = 0; $NodesAvd = 0; $NodesUnt = 0; $NodesBroke = 0; $NodesRedir = 0; $NodesChg = 0; $NodesExp = 0; $LocalTrav = 0; $LocalTest = 0; $LocalReus = 0; $LocalAvd = 0; $LocalUnt = 0; $LocalBroke = 0; $LocalRedir = 0; $LocalChg = 0; $LocalExp = 0; $RemotTrav = 0; $RemotTest = 0; $RemotReus = 0; $RemotAvd = 0; $RemotUnt = 0; $RemotBroke = 0; $RemotRedir = 0; $RemotChg = 0; $RemotExp = 0; } # ========================================================================== # update_summary(): Update the counters used for the Summary Tables # sub update_summary { ($TotalNodes, $NodesTest, $NodesTrav, $NodesAvd, $NodesUnt, $TotalLocal, $LocalTest, $LocalTrav, $LocalAvd, $LocalUnt) = &momhistory'nodes_used; $HrefsReus = $TotalHrefs - ($HrefsAvd + $HrefsUnt + $HrefsTest); $NodesReus = $TotalNodes - ($NodesAvd + $NodesUnt + $NodesTest); $LocalReus = $TotalLocal - ($LocalAvd + $LocalUnt + $LocalTest); $TotalRemot = $TotalNodes - $TotalLocal; $HrefsRmt = $TotalHrefs - $HrefsLoc; $NodesRmt = $TotalNodes - $TotalLocal; $RemotTrav = $NodesTrav - $LocalTrav; $RemotTest = $NodesTest - $LocalTest; $RemotReus = $NodesReus - $LocalReus; $RemotAvd = $NodesAvd - $LocalAvd; $RemotUnt = $NodesUnt - $LocalUnt; $RemotBroke = $NodesBroke - $LocalBroke; $RemotRedir = $NodesRedir - $LocalRedir; $RemotChg = $NodesChg - $LocalChg; $RemotExp = $NodesExp - $LocalExp; # Now update the process totals $ProcTotalHrefs += $TotalHrefs; $ProcHrefsTrav += $HrefsTrav; $ProcHrefsTest += $HrefsTest; $ProcHrefsAvd += $HrefsAvd; $ProcHrefsUnt += $HrefsUnt; $ProcHrefsBroke += $HrefsBroke; $ProcHrefsRedir += $HrefsRedir; $ProcHrefsChg += $HrefsChg; $ProcHrefsExp += $HrefsExp; $ProcHrefsLoc += $HrefsLoc; $ProcNodesTrav += $NodesTrav; $ProcNodesChg += $NodesChg; $ProcNodesExp += $NodesExp; $ProcLocalTrav += $LocalTrav; $ProcLocalChg += $LocalChg; $ProcLocalExp += $LocalExp; } # ========================================================================== # The summaries usually look like this: # # .---------------------------------------------------------------. # | References | Unique URLs | Local URLs | Remote URLs | # | number pct | number pct | number pct | number pct | # |---------------+---------------+---------------+---------------| # Traversed | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Tested | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Reused | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Avoided | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Untestable | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # |---------------+---------------+---------------+---------------| # Broken | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Redirected | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Changed NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # Expired NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # |---------------+---------------+---------------+---------------| # Local | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN 100.00 | 0 0.00 | # Remote | NNNNNN NNN.NN | NNNNNN NNN.NN | 0 0.00 | NNNNNN 100.00 | # |---------------+---------------+---------------+---------------| # Totals | NNNNNN 100.00 | NNNNNN NNN.NN | NNNNNN NNN.NN | NNNNNN NNN.NN | # `---------------------------------------------------------------' # $SummaryFormat = <<'EOF'; .---------------------------------------------------------------. | References | Unique URLs | Local URLs | Remote URLs | | number pct | number pct | number pct | number pct | |---------------+---------------+---------------+---------------| Traversed |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Tested |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Reused |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Avoided |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Untestable |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | |---------------+---------------+---------------+---------------| Broken |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Redirected |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Changed%3d |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Expired%3d |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | |---------------+---------------+---------------+---------------| Local |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | Remote |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | |---------------+---------------+---------------+---------------| Totals |%7d %6.2f |%7d %6.2f |%7d %6.2f |%7d %6.2f | `---------------------------------------------------------------' EOF # ========================================================================== # get_summary(): Generate the summary of results and return it as a string. # sub get_summary { local($th) = $TotalHrefs; if (!$th) { $th = 1; } # Avoid any divide by zero errors local($tn) = $TotalNodes; if (!$tn) { $tn = 1; } local($tl) = $TotalLocal; if (!$tl) { $tl = 1; } local($tr) = $TotalRemot; if (!$tr) { $tr = 1; } return sprintf($SummaryFormat, $HrefsTrav, (100*$HrefsTrav/$th), $NodesTrav, (100*$NodesTrav/$tn), $LocalTrav, (100*$LocalTrav/$tl), $RemotTrav, (100*$RemotTrav/$tr), $HrefsTest, (100*$HrefsTest/$th), $NodesTest, (100*$NodesTest/$tn), $LocalTest, (100*$LocalTest/$tl), $RemotTest, (100*$RemotTest/$tr), $HrefsReus, (100*$HrefsReus/$th), $NodesReus, (100*$NodesReus/$tn), $LocalReus, (100*$LocalReus/$tl), $RemotReus, (100*$RemotReus/$tr), $HrefsAvd, (100*$HrefsAvd/$th), $NodesAvd, (100*$NodesAvd/$tn), $LocalAvd, (100*$LocalAvd/$tl), $RemotAvd, (100*$RemotAvd/$tr), $HrefsUnt, (100*$HrefsUnt/$th), $NodesUnt, (100*$NodesUnt/$tn), $LocalUnt, (100*$LocalUnt/$tl), $RemotUnt, (100*$RemotUnt/$tr), $HrefsBroke, (100*$HrefsBroke/$th), $NodesBroke, (100*$NodesBroke/$tn), $LocalBroke, (100*$LocalBroke/$tl), $RemotBroke, (100*$RemotBroke/$tr), $HrefsRedir, (100*$HrefsRedir/$th), $NodesRedir, (100*$NodesRedir/$tn), $LocalRedir, (100*$LocalRedir/$tl), $RemotRedir, (100*$RemotRedir/$tr), $ChangeDays, $HrefsChg, (100*$HrefsChg/$th), $NodesChg, (100*$NodesChg/$tn), $LocalChg, (100*$LocalChg/$tl), $RemotChg, (100*$RemotChg/$tr), $ExpireDays, $HrefsExp, (100*$HrefsExp/$th), $NodesExp, (100*$NodesExp/$tn), $LocalExp, (100*$LocalExp/$tl), $RemotExp, (100*$RemotExp/$tr), $HrefsLoc, (100*$HrefsLoc/$th), $TotalLocal, (100*$TotalLocal/$tn), $TotalLocal, 100.0, 0, 0.0, $HrefsRmt, (100*$HrefsRmt/$th), $NodesRmt, (100*$NodesRmt/$tn), 0, 0.0, $TotalRemot, 100.0, $TotalHrefs, 100.0, $TotalNodes, (100*$TotalNodes/$th), $TotalLocal, (100*$TotalLocal/$th), $TotalRemot, (100*$TotalRemot/$th) ); } # ========================================================================== # get_procsum(): Generate the Process Summary and return it as a string. # This routine should only be called once at end of program. # sub get_procsum { local($ProcTotalNodes, $ProcNodesTest, $ProcNodesAvd, $ProcNodesUnt, $ProcNodesBroke, $ProcNodesRedir, $ProcTotalLocal, $ProcLocalTest, $ProcLocalAvd, $ProcLocalUnt, $ProcLocalBroke, $ProcLocalRedir) = &momhistory'nodes_processed; local($ProcHrefsReus) = $ProcTotalHrefs - ($ProcHrefsAvd + $ProcHrefsUnt + $ProcHrefsTest); local($ProcNodesReus) = $ProcTotalNodes - ($ProcNodesAvd + $ProcNodesUnt + $ProcNodesTest); local($ProcLocalReus) = $ProcTotalLocal - ($ProcLocalAvd + $ProcLocalUnt + $ProcLocalTest); local($ProcTotalRemot) = $ProcTotalNodes - $ProcTotalLocal; local($ProcHrefsRmt) = $ProcTotalHrefs - $ProcHrefsLoc; local($ProcNodesRmt) = $ProcTotalNodes - $ProcTotalLocal; local($ProcRemotTrav) = $ProcNodesTrav - $ProcLocalTrav; local($ProcRemotTest) = $ProcNodesTest - $ProcLocalTest; local($ProcRemotReus) = $ProcNodesReus - $ProcLocalReus; local($ProcRemotAvd) = $ProcNodesAvd - $ProcLocalAvd; local($ProcRemotUnt) = $ProcNodesUnt - $ProcLocalUnt; local($ProcRemotBroke) = $ProcNodesBroke - $ProcLocalBroke; local($ProcRemotRedir) = $ProcNodesRedir - $ProcLocalRedir; local($ProcRemotChg) = $ProcNodesChg - $ProcLocalChg; local($ProcRemotExp) = $ProcNodesExp - $ProcLocalExp; local($pth) = $ProcTotalHrefs; if (!$pth) { $pth = 1; } # Avoid any divide by zero errors local($ptn) = $ProcTotalNodes; if (!$ptn) { $ptn = 1; } local($ptl) = $ProcTotalLocal; if (!$ptl) { $ptl = 1; } local($ptr) = $ProcTotalRemot; if (!$ptr) { $ptr = 1; } return sprintf($SummaryFormat, $ProcHrefsTrav, (100*$ProcHrefsTrav/$pth), $ProcNodesTrav, (100*$ProcNodesTrav/$ptn), $ProcLocalTrav, (100*$ProcLocalTrav/$ptl), $ProcRemotTrav, (100*$ProcRemotTrav/$ptr), $ProcHrefsTest, (100*$ProcHrefsTest/$pth), $ProcNodesTest, (100*$ProcNodesTest/$ptn), $ProcLocalTest, (100*$ProcLocalTest/$ptl), $ProcRemotTest, (100*$ProcRemotTest/$ptr), $ProcHrefsReus, (100*$ProcHrefsReus/$pth), $ProcNodesReus, (100*$ProcNodesReus/$ptn), $ProcLocalReus, (100*$ProcLocalReus/$ptl), $ProcRemotReus, (100*$ProcRemotReus/$ptr), $ProcHrefsAvd, (100*$ProcHrefsAvd/$pth), $ProcNodesAvd, (100*$ProcNodesAvd/$ptn), $ProcLocalAvd, (100*$ProcLocalAvd/$ptl), $ProcRemotAvd, (100*$ProcRemotAvd/$ptr), $ProcHrefsUnt, (100*$ProcHrefsUnt/$pth), $ProcNodesUnt, (100*$ProcNodesUnt/$ptn), $ProcLocalUnt, (100*$ProcLocalUnt/$ptl), $ProcRemotUnt, (100*$ProcRemotUnt/$ptr), $ProcHrefsBroke, (100*$ProcHrefsBroke/$pth), $ProcNodesBroke, (100*$ProcNodesBroke/$ptn), $ProcLocalBroke, (100*$ProcLocalBroke/$ptl), $ProcRemotBroke, (100*$ProcRemotBroke/$ptr), $ProcHrefsRedir, (100*$ProcHrefsRedir/$pth), $ProcNodesRedir, (100*$ProcNodesRedir/$ptn), $ProcLocalRedir, (100*$ProcLocalRedir/$ptl), $ProcRemotRedir, (100*$ProcRemotRedir/$ptr), $ChangeDays, $ProcHrefsChg, (100*$ProcHrefsChg/$pth), $ProcNodesChg, (100*$ProcNodesChg/$ptn), $ProcLocalChg, (100*$ProcLocalChg/$ptl), $ProcRemotChg, (100*$ProcRemotChg/$ptr), $ExpireDays, $ProcHrefsExp, (100*$ProcHrefsExp/$pth), $ProcNodesExp, (100*$ProcNodesExp/$ptn), $ProcLocalExp, (100*$ProcLocalExp/$ptl), $ProcRemotExp, (100*$ProcRemotExp/$ptr), $ProcHrefsLoc, (100*$ProcHrefsLoc/$pth), $ProcTotalLocal, (100*$ProcTotalLocal/$ptn), $ProcTotalLocal, 100.0, 0, 0.0, $ProcHrefsRmt, (100*$ProcHrefsRmt/$pth), $ProcNodesRmt, (100*$ProcNodesRmt/$ptn), 0, 0.0, $ProcTotalRemot, 100.0, $ProcTotalHrefs, 100.0, $ProcTotalNodes, (100*$ProcTotalNodes/$pth), $ProcTotalLocal, (100*$ProcTotalLocal/$pth), $ProcTotalRemot, (100*$ProcTotalRemot/$pth) ); } # ========================================================================== 1;