home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / Perl_WWW_Utilities / webxref.pl < prev   
Encoding:
Perl Script  |  1996-04-24  |  22.4 KB  |  1,043 lines

  1. #!/usr/bin/perl
  2.  
  3. # webxref
  4. # ------
  5. # Webxref is a WWW link checker and cross referencing tool, intended
  6. # to quickly check a local set of HTML documents for missing files,
  7. # anchors etc. You simply call webxref with a HTML document as the parameter. 
  8. # Webxref compiles a list of HTML documents, URLs, name anchors, images etc 
  9. # and the html files that reference those, i.e. a cross-reference list.
  10. # usage: webxref [-nohttp -htmlonly -avoid regexp] file.html
  11. #
  12. #   -nohttp tells webxref *not* to check http:// URLs via the network
  13. #
  14. #   -htmlonly tells webxref to *only* inspect files with the .html
  15. #             extension for further links.
  16. #
  17. #   -silent tells webxref to only output error messages and keep quiet 
  18. #             about things that are ok.
  19. #
  20. #   -avoid regexp: when regexp matches a filename/URL/... the item is
  21. #             not further inspected. Make sure this parameter is
  22. #             supplied in quotes, else the shell will interpret various
  23. #             characters like *,$,.,?,...
  24. #
  25. # Examples
  26. #   webxref file.html
  27. #             checks file.html and files/URLs referenced from file.html
  28. #   webxref -nohttp file.html
  29. #             checks file.html, but not external URLs
  30. #   webxref -htmlonly file.html
  31. #             checks file.html, but no files without .html extension
  32. #   webxref -avoid '.*Archive.*' file.html
  33. #             checks file.html but avoids files with names containing
  34. #             'Archive'
  35. #   webxref -avoid '.*Archive.*|.*Distribution.*' file.html
  36. #             Same as above, but also files with names containing
  37. #             'Distribution' are skipped.
  38. #
  39. # Lists are made of:
  40. # - html files
  41. # - directories
  42. # - binary files (images)
  43. # - named anchors
  44. # - mailto's
  45. # - news
  46. # - ftp
  47. # - telnet
  48. # - gopher
  49. # - external URLs
  50. # - cgi-bin scripts
  51. # - file:'s
  52. # - files that can't be found
  53. # - files that are not world readable
  54. # - directories that can't be found
  55. # - name anchors that can't be found
  56. # - http:// ok references
  57. # - http:// failed references
  58. #
  59. # Written July 1995 by Rick Jansen at SARA as part of the SURFACE project 
  60. # (SURFnet Advanced Communication Environment)
  61. # email:  rick@sara.nl
  62. # url:    http://www.sara.nl/Rick.Jansen
  63. #
  64. # 11-JUL-95 lcheck version 0.0.0
  65. # 18-JUL-95 renamed webxref 0.0.1
  66. # 20-JUL-95 webxref 0.0.2
  67. # 21-JUL-95 webxref 0.0.3 root handling
  68. # 27-JUL-95 webxref 0.0.4 metachar interpretation in substitutions fixed
  69. # 28-JUL-95 webxref 0.0.5 pass associative array to sub
  70. # 08-AUG-95 webxref 0.0.6 parsing with temp file
  71. # 08-AUG-95 webxref 0.0.7 handle Welcome/welcome/index.html in case of dir
  72. # 08-AUG-95 webxref 0.0.8 'file:' refs
  73. # 10-AUG-95 webxref 0.0.9 Extensible default_files
  74. # 14-AUG-95 webxref 0.1.0 Some perl lint removed, cgi-bin added
  75. # 28-SEP-95 webxref 0.1.1 1-level external URL checking added
  76. # 04-OCT-95 webxref 0.1.2 options -nohttp -htmlonly and -avoid added
  77. # 04-OCT-95 webxref 0.1.3 Restriction on tags not being allowed to spread
  78. #                         over more than 1 source line removed, thanks to
  79. #                         Hans Hoppe (hopha@sci.kun.nl)
  80. # 10-OCT-95 webxref 0.1.4 -silent option
  81. # 15-APR-96 webxref 0.1.5 Temporary fix for $SOCK_STREAM
  82. #                          
  83. #
  84. # New versions can be obtained from:
  85. #   http://www.sara.nl/Rick.Jansen
  86.  
  87.  
  88. #---------------------------------------------
  89. # Configurable things:
  90.  
  91. # Files to try in case of a directory reference like ../..
  92. @default_files = ('Welcome.html','welcome.html','index.html',
  93.                   'index.shtml','README.html');
  94. #---------------------------------------------
  95.  
  96. $debug = 0;
  97.  
  98. $temp_file = "/tmp/webxref.$$";
  99.  
  100. #---------------------------------------------
  101. # HTTP status codes and messages
  102.  
  103. %OkStatusMsgs = (
  104.   200, "OK 200",
  105.   201, "CREATED 201",
  106.   202, "Accepted 202",
  107.   203, "Partial Information 203",
  108.   204, "No Response 204",
  109. );
  110.  
  111. %FailStatusMsgs = (
  112.   -1,  "Could not lookup server",
  113.   -2,  "Could not open socket",
  114.   -3,  "Could not bind socket",
  115.   -4,  "Could not connect",
  116.   301, "Found, but moved",
  117.   302, "Found, but data resides under different URL (add a /)",
  118.   303, "Method",
  119.   304, "Not Modified",
  120.   400, "Bad request",
  121.   401, "Unauthorized",
  122.   402, "PaymentRequired",
  123.   403, "Forbidden",
  124.   404, "Not found",
  125.   500, "Internal Error",
  126.   501, "Not implemented",
  127.   502, "Service temporarily overloaded",
  128.   503, "Gateway timeout ",
  129.   600, "Bad request",
  130.   601, "Not implemented",
  131.   602, "Connection failed (host not found?)",
  132.   603, "Timed out",
  133. );
  134.  
  135.  
  136. #---------------------------------------------
  137. # Process parameters
  138.  
  139. $Do_External_URLs = 1; # Default we do check external URLs
  140.  
  141. $HTML_only = 0;        # If 0, referenced files are checked for links
  142.                        # even if the file has no .html extension
  143.  
  144. $Avoid = "";           # Regexp to avoid certain URLs, files,...
  145.  
  146. $Silent = 0;           # If silent=1 only error msgs will be printed
  147.  
  148. $InFile = "";
  149. while ($ARGV[0] =~ /^-/) {
  150.   if ($ARGV[0] eq "-help") {&PrintHelp;}
  151.   elsif ($ARGV[0] eq "-nohttp") {$Do_External_URLs = 0; }
  152.   elsif ($ARGV[0] eq "-htmlonly") {$HTML_only = 1; }
  153.   elsif ($ARGV[0] eq "-silent") {$Silent = 1; }
  154.   elsif ($ARGV[0] eq "-avoid") {
  155.     shift;
  156.     $Avoid = $ARGV[0];
  157.     print "Avoided: $Avoid\n";
  158.     }
  159.   else {&PrintUsage;}
  160.  
  161.   shift;
  162. }
  163. $InFile = $ARGV[0];
  164.  
  165. if ($InFile eq "") {
  166.   print "No input file.\n";
  167.   exit;
  168. }
  169.  
  170.  
  171. #---------------------------------------------
  172.  
  173. # Does the file exist at all?
  174. stat($InFile);
  175. die "Cannot find file $InFile\n" unless -e $InFile;
  176.  
  177.  
  178. #---------------------------------------------
  179.  
  180. if ($debug) {
  181. print "=======================\n";
  182. print "\n input file: $InFile\n";
  183. }
  184.  
  185. # Assume webxref is called in the document root directory
  186. $root = `pwd`;
  187. chop($root);
  188.  
  189. if (!$Silent) { print "\nChecking $InFile\n\n"; }
  190. &Get_Refs($InFile,"<none>");
  191.  
  192. &Print_Lists;
  193.  
  194. # Check external URLs
  195. if ($Do_External_URLs) {
  196.   if (! $Silent) {
  197.   print <<"E_O_T";
  198.  
  199. - - - - - - - - - - - - - - - - - - - - - - - - - - -
  200. Going to really check external URLs via the network.
  201. This may take some time. Simply abort webxref if you
  202. are out of patience.
  203. - - - - - - - - - - - - - - - - - - - - - - - - - - -
  204. E_O_T
  205.  
  206.   }
  207.  
  208.   &Check_External_URLs(%HTTPList, "Checking external URLs:");
  209.   print "\nAll done.\n";
  210. }
  211.  
  212.  
  213. exit;
  214.  
  215.  
  216. sub PrintUsage {
  217.  
  218. print <<"E_O_T";
  219.  
  220. Usage: webxref -help -nohttp -htmlonly -silent -avoid regexp file.html
  221.  
  222. E_O_T
  223.  
  224. exit;
  225. }
  226.  
  227.  
  228.  
  229. sub PrintHelp {
  230.  
  231. print <<"E_O_T";
  232.  
  233. Usage: webxref -help -nohttp -htmlonly -silent -avoid regexp file.html
  234.  
  235.  -nohttp: do not check external URLs
  236.  -htmlonly: only inspect files with the .html extension
  237.  -silent: only output error/problem messages
  238.  -avoid regexp: avoid files with names matching regexp for inspection
  239.  
  240.  Examples
  241.    webxref file.html
  242.              checks file.html and files/URLs referenced from file.html
  243.    webxref -nohttp file.html
  244.              checks file.html, but not external URLs
  245.    webxref -htmlonly file.html
  246.              checks file.html, but only files with the .html extension
  247.    webxref -avoid '.*Archive.*' file.html
  248.              checks file.html but avoids files with names containing
  249.              'Archive'
  250.    webxref -avoid '.*Archive.*|.*Distribution.*' file.html
  251.              Same as above, but also files with names containing
  252.   
  253. E_O_T
  254.  
  255. exit;
  256. }
  257.  
  258. #---------------------------------------------
  259.  
  260. sub Get_PWD {
  261.  
  262. # Get the pwd, make sure it ends with a slash
  263.  
  264. local($dir);
  265.  
  266. $dir = `pwd`;
  267. $dir =~ s/\n//g;
  268. if (!($dir =~ m#.*/$#)) {
  269.   $dir = "$dir/";
  270. }
  271.  
  272. return $dir;
  273.  
  274. }
  275.  
  276.  
  277.  
  278. sub Get_Refs {
  279.  
  280. # Recursively get all referenced files a from the file
  281.  
  282. local(%newlist);
  283. local($file);
  284. local($dir);
  285. local($Old_Dir);
  286. local($filename);
  287.  
  288. $dir=&Dir_Name($_[0]);
  289. if ($dir eq "") {
  290.   $dir = &Get_PWD;
  291. }
  292. $file=&Base_Name($_[0]);
  293. #print "--------------------\n";
  294. if ($debug) {
  295. print "arg=$_[0]\n";
  296. print "dir=$dir\n";
  297. print "file=$file\n";
  298. }
  299.  
  300.  
  301.  
  302. # http?
  303. if ($_[0] =~ m/.*(http:.*)/i) {
  304.   if (!defined($HTTPList{$1})) {
  305.     $HTTPList{$1} = $_[1]; 
  306.     }
  307.   else {
  308.     $HTTPList{$1} = "$HTTPList{$1} $_[1]";
  309.   }
  310.   return;
  311. }
  312.  
  313.  
  314.  
  315. # ftp?
  316. if ($_[0] =~ m/.*(ftp:.*)/i) {
  317.   if (!defined($FTPList{$1})) {
  318.     $FTPList{$1} = $_[1]; 
  319.     }
  320.   else {
  321.     $FTPList{$1} = "$FTPList{$1} $_[1]";
  322.   }
  323.   return;
  324. }
  325.  
  326.  
  327. # telnet?
  328. if ($_[0] =~ m/.*(telnet:.*)/i) {
  329.   if (!defined($TelnetList{$1})) {
  330.     $TelnetList{$1} = $_[1]; 
  331.     }
  332.   else {
  333.     $TelnetList{$1} = "$TelnetList{$1} $_[1]";
  334.   }
  335.   return;
  336. }
  337.  
  338.  
  339. # gopher?
  340. if ($_[0] =~ m/.*(gopher:.*)/i) {
  341.   if (!defined($GopherList{$1})) {
  342.     $GopherList{$1} = $_[1]; 
  343.     }
  344.   else {
  345.     $GopherList{$1} = "$GopherList{$1} $_[1]";
  346.   }
  347.   return;
  348. }
  349.  
  350.  
  351.  
  352. # mailto?
  353. if ($_[0] =~ m/.*(mailto:.*)/i) {
  354.   if (!defined($MailList{$1})) {
  355.     $MailList{$1} = $_[1]; 
  356.     }
  357.   else {
  358.     $MailList{$1} = "$MailList{$1} $_[1]";
  359.   }
  360.   return;
  361. }
  362.  
  363.  
  364. # news?
  365. if ($_[0] =~ m/.*(news:.*)/i) {
  366.   if (!defined($NewsList{$1})) {
  367.     $NewsList{$1} = $_[1]; 
  368.     }
  369.   else {
  370.     $NewsList{$1} = "$NewsList{$1} $_[1]";
  371.   }
  372.   return;
  373. }
  374.  
  375.  
  376. # file:?
  377. if ($_[0] =~ m/.*(file:.*)/i) {
  378.   if (!defined($ExtFileList{$1})) {
  379.     $ExtFileList{$1} = $_[1]; 
  380.     }
  381.   else {
  382.     $ExtFileList{$1} = "$ExtFileList{$1} $_[1]";
  383.   }
  384.   return;
  385. }
  386.  
  387.  
  388. # cgi-bin script?
  389. if ($_[0] =~ m#(^/cgi-bin/.*)#i) {
  390.   $_[0] =~ m#(^/cgi-bin/.*)=.*#i;  # Delete cgi-parameters
  391.   
  392.   if (!defined($CGIList{$1})) {
  393.     $CGIList{$1} = $_[1]; 
  394.     }
  395.   else {
  396.     $CGIList{$1} = "$CGIList{$1} $_[1]";
  397.   }
  398.   return;
  399. }
  400.  
  401.  
  402. # directory reference?
  403. if ($file eq "") {
  404.  
  405.   if ($debug) {
  406.     print "$dir must be a dir, refd by $_[1]!\n";
  407.   }
  408.   if (-d $_[0]) {
  409.     if (!defined($DirList{$_[0]})) {
  410.       $DirList{$_[0]} = $_[1];
  411.       }
  412.     else {
  413.       $DirList{$_[0]} = "$DirList{$_[0]} $_[1]";
  414.     }
  415.   }
  416.   else {
  417.  
  418.     if (!defined($DirNotFoundList{$_[0]})) {
  419.       $DirNotFoundList{$_[0]} = $_[1];
  420.     }
  421.     else {
  422.       $DirNotFoundList{$_[0]} = "$DirNotFoundList{$_[0]} $_[1]";
  423.     }
  424.   }
  425.  
  426.   return;
  427. }
  428.  
  429.  
  430.  
  431. # Move to the specified directory
  432. $Old_Dir = &Get_PWD;
  433. if ($debug) {
  434.   print "Chdir to $dir\n";
  435. }
  436. chdir($dir);
  437. $dir=&Get_PWD;
  438. if ($debug) {
  439.   print "Now in $dir\n";
  440. }
  441. $filename = $dir . $file;
  442.  
  443. if (! $Silent) {
  444.   print "Checking: $filename\n";
  445. }
  446.  
  447. # Is it a reference to a specific section? (a file#section reference)
  448. if ($filename =~ m/(.+)#(.+)/) {
  449.   $filename = "$1#$2";
  450.   if (&CheckAnchor($1, $2) ) {
  451.     #print "** Anchor $2 is present in file $1\n"; 
  452.  
  453.     # Add to the list of anchors
  454.     if (!defined($AnchorList{$filename})) {
  455.       $AnchorList{$filename} = $_[1]; 
  456.       }
  457.     else {
  458.       $AnchorList{$filename} = "$AnchorList{$filename} $_[1]";
  459.     }
  460.   }
  461.   else {
  462.     print "xx Anchor $2 is NOT present in file $1\n"; 
  463.     print "xx Referenced by: $_[1]\n";
  464.     #print "Anchor filename: $filename\n";
  465.  
  466.     # Add to the list of lost anchors
  467.     if (!defined($LostAnchorList{$filename})) {
  468.       $LostAnchorList{$filename} = $_[1]; 
  469.       }
  470.     else {
  471.       $LostAnchorList{$filename} = "$LostAnchorList{$filename} $_[1]";
  472.     }
  473.     
  474.   }
  475.   return;
  476. }
  477.  
  478. #
  479. # Add to the list of already tested files
  480. #
  481.  
  482. # If the "file" is a directory try Welcome/welcome/index.html
  483. if (-d $filename) {
  484.   #print "xx $filename is a directory, trying Welcome/welcome/index.html.\n";
  485.  
  486.   $found = 0;
  487.   foreach $default_file (@default_files) {
  488.     #print "Trying $default_file\n";
  489.     if (-f ($file . '/' . $default_file)) {
  490.       $dirname=$filename;
  491.       $file= $default_file;
  492.       $found = 1;
  493.       last;
  494.     }
  495.   }
  496.  
  497.   if (! $found) {
  498.     print "xx No Welcome/welcome/index.html can be found in $filename\n";
  499.     print "xx Referenced by: $_[1]\n";
  500.   
  501.     # Add to list of lost files
  502.     if (!defined($LostFileList{$filename})) {
  503.       $LostFileList{$filename} = $_[1]; 
  504.       }
  505.     else {
  506.       $LostFileList{$filename} = "$LostFileList{$filename} $_[1]";
  507.     }
  508.     return;
  509.   }
  510.  
  511.   # Move to the specified directory
  512.   if ($debug) {
  513.     print "Chdir to $dirname\n";
  514.   }
  515.   chdir($dirname);
  516.   $dir=&Get_PWD;
  517.   if ($debug) {
  518.     print "Now in $dir\n";
  519.   }
  520.   $filename = $dir . $file;
  521.   if ($debug) {
  522.     print "** Filename is now: $filename\n";
  523.     print "** Dirname is now: $dir\n";
  524.   }
  525. }
  526.  
  527. if (! -f $filename) {
  528.   print "xx $filename cannot be found\n";
  529.   print "xx Referenced by: $_[1]\n";
  530.  
  531.   # Add to list of lost files
  532.   if (!defined($LostFileList{$filename})) {
  533.     $LostFileList{$filename} = $_[1]; 
  534.     }
  535.   else {
  536.     $LostFileList{$filename} = "$LostFileList{$filename} $_[1]";
  537.   }
  538.  
  539.   return;
  540. }
  541.  
  542. # Binary file? (pictures,...)
  543. if (-B $filename) {
  544.   if ($debug) {
  545.     print "** Binary file added to images";
  546.   }
  547.   if (defined($ImageFileList{$filename})) {
  548.     return;
  549.   }
  550.   if (!defined($ImageFileList{$filename})) {
  551.     $ImageFileList{$filename} = $_[1];  # Define!
  552.     }
  553.   else {
  554.     $ImageFileList{$filename} = "$ImageFileList{$filename} $_[1]";
  555.   }
  556.   if ($debug) {
  557.     print "\n\nAdded: $filename to list of images\n";
  558.   }
  559.   
  560.   return;
  561. }
  562.  
  563. # else it's a text (html)file
  564. if (!defined($FileList{$filename})) {
  565.   $FileList{$filename} = $_[1];  # Define!
  566.   }
  567. else {
  568.   $FileList{$filename} = "$FileList{$filename} $_[1]";
  569.   
  570.   return;  # Already did this file
  571. }
  572. if ($debug) {
  573.   print "** Added: $filename \n";
  574. }
  575.  
  576.  
  577. # World readable?
  578. ($_,$_,$mode) = stat($filename);
  579. $readmode = ($mode & 4);
  580. if ($readmode == 0) {
  581.   # Not world readable, add to list
  582.   #print "xx Warning: $filename is not world readable\n";
  583.   if (!defined($UnreadableList{$filename})) {
  584.     $UnreadableList{$filename} = $_[1];
  585.     }
  586.   else {
  587.     $UnreadableList{$filename} = "$UnreadableList{$filename} $_[1]";
  588.   }
  589. }
  590.  
  591. if ($HTML_only) {
  592.   # Filename *must* have extension .html, else we don't inspect it.
  593.   if ($filename !~ /.*\.html$/i) {return;}
  594. }
  595.  
  596. # Apply the regexp to avoid certain files
  597. if ($Avoid ne "") {
  598.   if ($filename =~ m/$Avoid/) { 
  599.     print "** The above file is avoided.\n"; 
  600.     return;
  601.   }
  602. }
  603.  
  604.  
  605. $err = 0;
  606. open(HTML, $filename) || ($err = 1);
  607. if ($err) {
  608.   print "xx Could not open file $filename\n";
  609.   return; 
  610. }
  611.  
  612. # Make sure all <somethings start on a new line in temp file,
  613. # resulting in one thingie per line
  614.  
  615. #Old:
  616. #open(TEMP,">$temp_file") || die "Could not create $temp_file\n";
  617. #while (<HTML>) {
  618. #  s/</\n</g;
  619. #  print TEMP;
  620. #}
  621. #close(TEMP);
  622.  
  623. # Read the file into a big string and remove crud in between tags.
  624. # Code thanks to Hans Hoppe (hopha@sci.kun.nl) 04-OCT-95
  625. open(TEMP,">$temp_file") || die "Could not create $temp_file\n";
  626. $offset=0;
  627. do {
  628.   $size=read(HTML,$html_text,32768,$offset);
  629.   $offset=$offset+$size;
  630. } until $size != 32768;
  631. close(HTML);
  632. #$html_text =~ s/\n/ /gs;
  633. $html_text =~ s/\n/ /g;
  634. $html_text =~ s/[^<]*//;
  635. $html_text =~ s/(<[^>]*>)[^<]*/\1\n/g;
  636. print TEMP "$html_text";
  637. $html_text="";
  638. close(TEMP);
  639.  
  640. open(HTML, $temp_file) || die "Could not open $temp_file\n";
  641. while (<HTML>) {
  642.   chop;
  643.  
  644.   # <a href=...
  645.   if (/<a\s+.*href\s*=/i) {
  646.     s/<a\s+.*href *=//i;   # <a href=  at start
  647.     s/\s+.*//;
  648.     s/\s+.*>.*//;          # trailing stuff
  649.     s/>.*$//i;             # remove >'s
  650.     s/"//g;                # Unquote file names
  651.     s/^\s*//;              # Remove spaces at start
  652.     s/\s*$//;              # Remove spaces at end
  653.  
  654.     # Link to section within current document?
  655.     if (m/^#.*/) {
  656.       $file_w_anchor = $filename;
  657.       $file_w_anchor =~ s#.*/##;
  658.       if ($debug) {
  659.         print "file_w_anchor: $file_w_anchor\n";
  660.         print "Added to newlist: $file_w_anchor$_\n";
  661.       }
  662.       $newlist{"$file_w_anchor$_"} = 1;  # Check this file plus anchor later
  663.       }
  664.     # Link to another document?
  665.     else {
  666.       if ($debug) {
  667.         print "added to newlist: $_\n";
  668.       }
  669.       $newlist{$_} = 1;
  670.     }
  671.  
  672.   }
  673.  
  674.   # <img src=...
  675.   # NB: <img and src= must be on same line
  676.   if (/<img\s+.*src\s*=/i) {
  677.     s/<img\s+.*src\s*=//i;
  678.     s/\s+.*//;
  679.     s/\s+.*>.*//;
  680.     s/>.*$//i;             # remove >'s
  681.     s/"//g;                # Unquote file names
  682.     s/^\s*//;              # Remove spaces at start
  683.     s/\s*$//;              # Remove spaces at end
  684.  
  685.     # Add file to the list
  686.     $newlist{$_} = 1;
  687.   }
  688.  
  689. }
  690.  
  691. close(HTML);
  692.  
  693. chdir($Old_Dir);
  694.  
  695. if ($debug) {
  696.   # List files
  697.   print "\nNewlist:\n";
  698.   foreach $file (keys(%newlist)) {
  699.     print "$file \n";
  700.   }
  701. }
  702.  
  703. # Walk the list
  704. foreach $file (keys(%newlist)) {
  705.   # if file is //something insert a http:
  706.   if ($file =~ m#^//.*#) {
  707.     $file = "http:" . $file;
  708.   }
  709.  
  710.   $Notlocal_file = $dir . $file;
  711.  
  712.   # If file is /something it's a reference from the root document.
  713.   # It can also be a cgi-bin reference!
  714.   if ($file =~ m#^/cgi-bin/.*#) {
  715.     $Notlocal_file = $file;
  716.     }
  717.   elsif ($file =~ m#^/.*#) {
  718.     $Notlocal_file = "$root$file";
  719.   }
  720.  
  721.   $Notlocal_ref_filename = $filename;
  722.   if ($debug) {
  723.     print "\nCalling GR with $Notlocal_file\n";
  724.     print "Referenced by: $Notlocal_ref_filename\n";
  725.   }
  726.   &Get_Refs($Notlocal_file, $Notlocal_ref_filename);
  727. }
  728.  
  729. unlink($temp_file);
  730.  
  731. } #sub Get_Refs
  732.  
  733. #---------------------------------------------
  734.  
  735. sub Base_Name {
  736.  
  737. # return basename,
  738. # e.g. /home/sscprick/.WWW/Welcome.html 
  739. # returns: Welcome.html
  740.  
  741. local($local_filename)=$_[0];
  742. $local_filename =~ s#.*/##;  # remove the directory name -> file name
  743.  
  744. $local_filename;
  745. }
  746.  
  747. sub Dir_Name {
  748.  
  749. # return dirname,
  750. # e.g. /home/sscprick/.WWW/Welcome.html 
  751. # returns: /home/sscprick/.WWW/
  752.  
  753. local($local_filename)=$_[0];
  754. $local_filename =~ s#.*/##;  # remove the directory name -> file name
  755. local($local_dirname) = $_[0];
  756. $local_filename =~ s/(\W)/\\$1/g;  # escape regexp chars
  757. $local_dirname =~ s/$local_filename$//; # wipe filename at end -> dir name
  758.  
  759. $local_dirname;
  760. }
  761.  
  762.  
  763. sub CheckAnchor {
  764.  
  765. # See if #section anchor is present in file
  766.  
  767. local($fn, $anchor) = @_;
  768. $anchor =~ s/(\W)/\\$1/g;  # quote rexep chars
  769.  
  770. open(CH_HTML, $fn) || die "xx Could not open $fn\n";
  771. while (<CH_HTML>) {
  772.   chop;
  773.   if (/<a +name *= *"*$anchor"*/i) {
  774.     close(CH_HTML);
  775.     return 1; 
  776.   }
  777. }
  778.  
  779. close(CH_HTML);
  780. return 0;
  781.  
  782. } # sub CheckAnchor
  783.  
  784.  
  785. #---------------------------------------------
  786.  
  787. sub Check_External_URLs {
  788.  
  789.  
  790. local(%list, $header) = @_;
  791. local($URL);
  792.  
  793. if (!$Silent) { print "\n\n----------------\n$header\n"; } 
  794. @TheList=keys(%list);
  795. @SortedList = sort @TheList;
  796.  
  797. foreach $URL (@SortedList) {
  798.   if (! $Silent) { print "$URL \n"; }
  799.  
  800.   if (defined($HTTPStatusList{$URL})) {
  801.     # Already checked on this one
  802.     next;
  803.   }
  804.   else {
  805.     $rcode = &Check_URL($URL);
  806.   }
  807.  
  808.   if (defined($OkStatusMsgs{$rcode})) {
  809.     # URL is ok, server responds and all.
  810.     if (! $Silent) { print "  Ok\n"; }
  811.     $HTTP_OK_List{$URL} = $HTTPList{$URL};  # The references
  812.   }
  813.   else {
  814.     # Something is wrong.
  815.     if (defined($FailStatusMsgs{$rcode})) {
  816.       if (! $Silent) { print "  xx Failed: $FailStatusMsgs{$rcode}\n"; }
  817.     }
  818.     else {
  819.       if (! $Silent) { print "  xx Failed with code $rcode\n"; }
  820.     }
  821.     $HTTP_Fail_List{$URL} = $rcode;
  822.   }
  823. }
  824.  
  825. if (! $Silent) { &Print_List(%HTTP_OK_List,"URLs checked ok:"); }
  826. &Print_Failed_URL_List(%HTTP_Fail_List, "Failed URLs:");
  827.  
  828. }
  829.  
  830.  
  831.  
  832. sub Print_Failed_URL_List {
  833.  
  834. local(%list, $header) = @_;
  835. local($URL);
  836.  
  837. # Don't list empty lists
  838. if (! %list) {return};
  839.  
  840. print "\n\n----------------\n$header\n";
  841. @TheList=keys(%list);
  842. @SortedList = sort @TheList;
  843.  
  844. foreach $URL (@SortedList) {
  845.   print "$URL \n";
  846.   $rcode = $HTTP_Fail_List{$URL};
  847.   print "  Status: $rcode ($FailStatusMsgs{$rcode})\n";
  848.  
  849.   @lost = split(/ /,$HTTPList{$URL});
  850.   @sortlost = sort @lost;
  851.   print "  Referenced by:\n";
  852.   foreach $lostURL (@sortlost) {
  853.     print "  $lostURL\n";
  854.   }
  855. }
  856.  
  857. }  # sub Print_Failed_URL_List
  858.  
  859.  
  860.  
  861.  
  862.  
  863. sub Check_URL {
  864.  
  865. # http://host:port/path
  866.  
  867. local($URL) = @_;
  868.  
  869. if ($URL !~ m#^http://.*#i) { 
  870.   print "wrong format http!\n";
  871.   return;
  872. }
  873. else {
  874.  
  875.   #if ($URL =~ m#^http://([\w-\.]+)(:|$|/)#) {
  876.  
  877.   # Get the host and port
  878.   if ($URL =~ m#^http://([\w-\.]+):?(\d*)($|/(.*))#) {
  879.     $host = $1;
  880.     $port = $2;
  881.     $path = $3;
  882.   }
  883.   if ($path eq "") { $path = '/'; }
  884.   if ($port eq "") { $port = 80; }
  885.  
  886.   # Delete name anchor. (check if the anchor is present in the doc?)
  887.   $path =~ s/#.*//;
  888.   # Delete parameters
  889.   #$path =~ s/\?.*//;
  890.  
  891.   #print "-->\n URL: $URL\n host: $host\n port: $port\n path: $path\n";
  892. }
  893.  
  894.  
  895. # The following is largely taken from the Camel book, chapter 6
  896.  
  897. $AF_INET = 2;
  898. $SOCK_STREAM = 1;
  899.  
  900. $sockaddr = 'S n a4 x8';
  901.  
  902. chop($hostname = `hostname`);
  903.  
  904. ($name,$aliases,$proto) = getprotobyname('tcp');
  905. ($name,$aliases,$port) = getservbyname($port,'tcp') unless $port =~ /^\d+$/;
  906. ($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
  907. if (!(($name,$aliases,$type,$len,$thataddr) = gethostbyname($host))) {
  908.   return -1;
  909. }
  910.  
  911. $this = pack($sockaddr, $AF_INET, 0, $thisaddr);
  912. $that = pack($sockaddr, $AF_INET, $port, $thataddr);
  913.  
  914. # Make the socket filehandle.
  915. # ** Temporary fix, this is NOT The way to do it. 15-APR-96
  916. if (!(socket(S, $AF_INET, $SOCK_STREAM, $proto))) {
  917.   $SOCK_STREAM = 2;
  918.   if (!(socket(S, $AF_INET, $SOCK_STREAM, $proto))) { return -2; }
  919. }
  920.  
  921. # Give the socket an address
  922. if (!(bind(S, $this))) {
  923.   return -3;
  924. }
  925.  
  926. if (!(connect(S,$that))) {
  927.   return -4;
  928. }
  929.  
  930. select(S); $| = 1; select(STDOUT);
  931.  
  932. print S "HEAD $path HTTP/1.0\n\n";
  933.  
  934. $response = <S>;
  935. ($protocol, $status) = split(/ /, $response);
  936. while (<S>) {
  937.   #print;
  938. }
  939. close(S);
  940.  
  941. #print "Status: $status\n";
  942. return $status;
  943.  
  944. }
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952. #---------------------------------------------
  953.  
  954. sub Print_List {
  955.  
  956. local(%list, $header) = @_;
  957. local($file);
  958.  
  959. # Don't list empty lists
  960. if (! %list) {return};
  961.  
  962. print "\n\n----------------\n$header\n";
  963. @TheList=keys(%list);
  964. @SortedList = sort @TheList;
  965.  
  966. foreach $file (@SortedList) {
  967.   print "$file \n";
  968.   @lost = split(/ /,$list{$file});
  969.   @sortlost = sort @lost;
  970.   print "  Referenced by:\n";
  971.   foreach $lostfile (@sortlost) {
  972.     print "  $lostfile\n";
  973.   }
  974. }
  975.  
  976. }  # sub Print_List
  977.  
  978.  
  979.  
  980.  
  981. sub Print_Lists {
  982.  
  983. # Print lists
  984.  
  985. # List all files found
  986. if (!$Silent) { &Print_List(%FileList,"Web documents found:");}
  987.  
  988. # List of directories referenced
  989. if (!$Silent) { &Print_List(%DirList,"Directories:");}
  990.  
  991. # List of images referenced
  992. if (!$Silent) { &Print_List(%ImageFileList,"Images:");}
  993.  
  994. # List of mailto's
  995. if (!$Silent) { &Print_List(%MailList,"Mailto:");}
  996.  
  997. # List of ftp's
  998. if (!$Silent) { &Print_List(%FTPList,"ftp:");}
  999.  
  1000. # List of telnets
  1001. if (!$Silent) { &Print_List(%TelnetList,"telnet:");}
  1002.  
  1003. # List of gophers
  1004. if (!$Silent) { &Print_List(%GopherList,"gopher:");}
  1005.  
  1006. # List of news
  1007. if (!$Silent) { &Print_List(%NewsList,"News:");}
  1008.  
  1009. # List of http's
  1010. if (!$Silent) { &Print_List(%HTTPList,"External URLs:");}
  1011.  
  1012. # List of file:'s
  1013. if (!$Silent) { &Print_List(%ExtFileList,"External file:");}
  1014.  
  1015. # List of cgi-bin scripts/forms
  1016. if (!$Silent) { &Print_List(%CGIList,"cgi-bin scripts/forms:");}
  1017.  
  1018. # List of name anchors
  1019. if (!$Silent) { &Print_List(%AnchorList,"Name anchors found:");}
  1020.  
  1021. # List of files that can't be found
  1022. &Print_List(%LostFileList,"Files not found:");
  1023.  
  1024. # List of files that are not world readable
  1025. &Print_List(%UnreadableList,"Files not world readable:");
  1026.  
  1027. # List of directories that can't be found
  1028. &Print_List(%DirNotFoundList,"Directories not found:");
  1029.  
  1030. # List of name anchors not found
  1031. &Print_List(%LostAnchorList,"Name anchors not found:");
  1032.  
  1033. if ($HTML_only) { print "\nDone.\n"; }
  1034.  
  1035. } #sub Print_Lists
  1036.  
  1037.  
  1038.  
  1039. # This is the last line of the webxref script really.
  1040. # If this line is missi
  1041.  
  1042.