
# ----------------- SUBS ----------------- #

sub GetFileList {
  use strict;
  my $dir = shift || return;
  my ($cmd,@htmlfiles);

  chdir $dir;
  
  foreach (qw(html htm shtml)) {
    $cmd = "find ".$dir." -name '*.".$_."' -print";
    push(@htmlfiles, `$cmd`);
  }
  
  chomp @htmlfiles;
  return @htmlfiles;
}

sub GetNextPair {
  use strict;
  use locale;
  my $line = shift;
  my $value = "";
  my ($key,$nline);

  ($key,$nline) = $line =~ /^\s*([\w-]+)\s*=\s*(.*)$/;
  if ($nline =~ /^\"/) {
    ($value,$nline) = $nline =~ /^\"([^\"]+)\"\s*(.*)$/;
  } elsif ($nline =~ /^\'/) {
    ($value,$nline) = $nline =~ /^\'([^\']+)\'\s*(.*)$/;
  } elsif (($key eq "") and ($line ne "")) {
    ($key,$nline) = $line =~ /^\s*([\w-]+)\s*(.*)$/;
  } else {
    ($value,$nline) = $nline =~ /^\s*(\S+)\s+(.*)$/;
  }
  return ($key, $value, $nline);
}

sub HeaderHtml {
    my $logo = shift;

return <<EOH;
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>HTML Meta Tag and Header Tag Explorer</title>
<meta name="Generator" content="EditPlus">
<meta name="Author" content="Steve Horsburgh">
<meta name="Keywords" content="HTML,meta,meta tag,header,header tag,analyze,analyzer,explorer,tag analysis,html tag analysis">
<meta name="Description" content="HTML Meta Tag and Header Tag Explorer and Analyzer">
 <meta http-equiv="Expires" content="-1">
</head>
<body bgcolor="#ffffff" style="margin:0" marginwidth=0 marginheight=0 topmargin=0 leftmargin=0>
<table width="100%" border=0 cellspacing=0 cellpadding=0>
 <tr>
  <td bgcolor="#000042"><img src="$logo" border=0><font color="white" size=5>&nbsp;HTML Tag Analyzer</font></td>
  <td bgcolor="#000042" align="right"><font color="yellow" size=2 face="arial,helvetica,sans-serif">designed by </font><a href="http://www.horsburgh.com/"><font color="white" size=2><b>Horsburgh.com</b></font></a>&nbsp;</td>
 </tr>
</table>
EOH
}

sub GenHtml {
  use strict;
  my ($dir,%Buf) = @_;
  my($file,$mt,$tag,$f,$h);
  my @mtags = @::MTags;
  my @htags = @::HList;
  my $error = $::Error;
  $error =~ s/&/&amp;/g;
  $error =~ s/</&lt;/g;
  $error = "<pre>".$error."</pre>" if $error;
  my $cols = $#mtags + $#htags + 4;
  my $hdr = <<EOP;
<table border=0 width="100%" cellspacing=0 cellpadding=0>
 <tr valign="top">
  <td><strong>Analysis of HTML files in: $dir</strong></td>
  <td align="right"><a href="javascript:top.history.go(-1)">Return</a></td>
 </tr>
</table>
$error
<table border=1 width="100%">
EOP

my $html = "";
my $titles = " <tr>\n";
my $createtitles = 1;
my(@metatags);

  foreach $file (sort keys %Buf) {
    ($f = $Buf{$file}{name}) =~ s/^\.\///i;
    $Buf{$file}{meta}{'content-type'}{content} ||= "text/html";
    $html .= " <tr valign=\"top\">\n";
    $html .= "  <td><small>".&Encode($f)."</small></td>\n";
    $html .= "  <td><small>".&Encode($Buf{$file}{title})."</small></td>\n" if $::in{'title'};
    $titles .= "  <td align=\"center\" bgcolor=\"#333382\"><strong><font color=\"white\">File</font></strong></td>\n" if $createtitles;
    $titles .= "  <td align=\"center\" bgcolor=\"#333382\"><strong><font color=\"white\">Title</font></strong></td>\n" if ($createtitles and $::in{'title'});

    if ($::in{'other'}) {
      if ($createtitles) {
        foreach $file (keys %Buf) {
          foreach $tag (keys %{$Buf{$file}{meta}}) {
            next unless $tag;
            push(@metatags,$tag) unless grep(/^$tag$/,@metatags);
          }
        }
      }
      foreach $tag (sort @metatags) {
        $titles .= "  <td align=\"center\" bgcolor=\"#333382\"><strong><font color=\"white\">".ucfirst(lc($tag))."</font></strong></td>\n" if $createtitles;
        $html .= "  <td><small>".($Buf{$file}{meta}{$tag}{content}?&Encode($Buf{$file}{meta}{$tag}{content}):'&nbsp;');
        foreach (qw(scheme lang dir)) {
          $html .= "<br>".$_.' = '.&Encode($Buf{$file}{meta}{$tag}{$_}) if defined $Buf{$file}{meta}{$tag}{$_};
        }
        $html =~ s/, $//;
        $html =~ s/,/, /g;
        $html .= "</small></td>\n";
    }
    } else {
      foreach $tag (@mtags) {
        $titles .= "  <td align=\"center\" bgcolor=\"#333382\"><strong><font color=\"white\">".ucfirst(lc($tag))."</font></strong></td>\n" if $createtitles;
        $html .= "  <td><small>".($Buf{$file}{meta}{$tag}{content}?&Encode($Buf{$file}{meta}{$tag}{content}):'&nbsp;');
        foreach (qw(scheme lang dir)) {
          $html .= "<br>".$_.' = '.&Encode($Buf{$file}{meta}{$tag}{$_}) if defined $Buf{$file}{meta}{$tag}{$_};
        }
        $html =~ s/, $//;
        $html =~ s/,/, /g;
        $html .= "</small></td>\n";
      }
    }

    if ($::in{'links'}) {
      $titles .= "  <td align=\"center\" bgcolor=\"#333382\"><strong><font color=\"white\">Links</font></strong></td>\n" if $createtitles;
      $html .= "  <td><small>";
      foreach $tag (sort {$a <=> $b} keys %{$Buf{$file}{'link'}}) {
        $html .= "Link #".$tag."<br>";
        foreach (qw(rel rev type href media charset hreflang lang title style target dir)) {
          $html .= '&nbsp;&nbsp;'.$_.'='.$Buf{$file}{'link'}{$tag}{$_}."<br>" if $Buf{$file}{'link'}{$tag}{$_};
        }
      }
      $html =~ s/, $//;
      $html .= "</small></td>\n";
    }

    foreach $tag (@htags) {
      $titles .= "  <td align=\"center\" bgcolor=\"#333382\"><strong><font color=\"white\">".ucfirst(lc($tag))."</font></strong></td>\n" if $createtitles;
      if ($#{$Buf{$file}{headers}{$tag}} > 0) {
        $h = "<ol><li>".join('</li><li>',&Encode(@{$Buf{$file}{headers}{$tag}}))."</li></ol>\n";
      } else {
        $h = &Encode(${$Buf{$file}{headers}{$tag}}[0]);
      }
      $h =~ s/\&lt;\s*$tag[^>]*>//ig; $h =~ s/\&lt;\s*\/$tag[^>]*>//ig;
      $html .= "  <td><small>".($h?$h:'&nbsp;')."</small></td>\n";
    }

    $html .= " </tr>\n";
    $titles .= " </tr>\n" if $createtitles;
    $createtitles = 0;
  }

  return $hdr.$titles.$html."</table>\n<p><strong>Files Processed:</strong><small><ol>".$::Pfiles."</ol></small></p>".
         "<hr><small><em>Copyright &copy; 2000, ".
         "<a href=\"http://www.horsburgh.com/\">Horsburgh.com</a>. ".
         "All Rights Reserved.</em></small></body>\n</html>\n";
}

sub Encode {
    my @vals = @_;
    foreach $i (0..$#vals) {
      $vals[$i] =~ s/&/&amp;/g;
      $vals[$i] =~ s/</&lt;/g;
    }
    return $#vals > 0 ? @vals : $vals[0];
}

sub TitleInfo {
  use strict;
  my @titlelist = @_;
  if ($#titlelist == 0) {
    $titlelist[0] =~ s/^\s*<\s*title\s*>\s*(.*)\s*<\/title\s*>.*$/$1/i;
    chomp $titlelist[0];
    return $titlelist[0];
  } else {
    return ($#titlelist < 0 ? 'None' : 'Warning too many title tags');
  }
}

sub Opening {
    my $action = shift;
return <<EOP;
<body bgcolor="#FFFFFF">
 <script language="javascript">
 <!--
  function checkAll(val) {
   if (document.all) {
     obj = document.all;
   } else {
     obj = document.frm;
   }
   obj.title.checked = val;
   obj.links.checked = val;
   obj.author.checked = val;
   obj.content_type.checked = val;
   obj.copyright.checked = val;
   obj.description.checked = val;
   obj.expires.checked = val;
   obj.generator.checked = val;
   obj.keywords.checked = val;
   obj.reply_to.checked = val;
   obj.other.checked = val;
   obj.h1.checked = val;
   obj.h2.checked = val;
   obj.h3.checked = val;
   obj.h4.checked = val;
   obj.h5.checked = val;
   obj.h6.checked = val;
  }
 // -->
 </script>
 <form method=get name=frm action="$action">
  <table border=0>
   <tr valign="top">
    <td><font size=6 color="#6666a7">&nbsp;1. </font></td>
    <td><font size=6>&nbsp;</font>Enter the full path specification (directory) of the files you want to analyze. 
        All HTML files in the directory and subdirectories will be analyzed. Hundreds of files might take a few minutes to process.<br>
        <font size=6>&nbsp;</font>Directory:<input type=text name=dir size=40></td>
   </tr>
   <tr valign="top">
    <td><font size=6 color="#6666a7">&nbsp;2. </font></td>
    <td><font size=6>&nbsp;</font>Choose which tags to analyze.
        <input type=button value="Check All" onClick="checkAll(true);return false">
        <input type=button value="Clear All" onClick="checkAll(false);return false">
       <table border=0>
        <tr valign="top">
         <td>&nbsp;&nbsp;&nbsp;</td>
         <td><strong>Header&nbsp;Tags:</strong></td>
         <td><input type=checkbox name=title value=1 checked><small>Title&nbsp;</small>
             <input type=checkbox name=links value=1><small>Link&nbsp;</small></td>
        </tr>
        <tr valign="top">
         <td>&nbsp;&nbsp;&nbsp;</td>
         <td><strong>Meta&nbsp;Tags:</strong></td>
         <td><input type=checkbox name=author value=1><small>Author&nbsp;</small>
             <input type=checkbox name=content_type value=1><small>Content-type&nbsp;</small>
             <input type=checkbox name=copyright value=1><small>Copyright&nbsp;</small>
             <input type=checkbox name=description value=1 checked><small>Description&nbsp;</small>
             <input type=checkbox name=expires value=1><small>Expires&nbsp;</small>
             <input type=checkbox name=generator value=1><small>Generator&nbsp;</small>
             <input type=checkbox name=keywords value=1 checked><small>Keywords&nbsp;</small>
             <input type=checkbox name=reply_to value=1><small>Reply-to&nbsp;</small>
             <input type=checkbox name=other value=1><small>All&nbsp;Meta&nbsp;Tags&nbsp;</small></td>
        </tr>
        <tr valign="top">
         <td>&nbsp;&nbsp;&nbsp;</td>
         <td><strong>Headings:</strong></td>
         <td><input type=checkbox name=h1 value=1 checked><small>H1&nbsp;</small>
             <input type=checkbox name=h2 value=1 checked><small>H2&nbsp;</small>
             <input type=checkbox name=h3 value=1><small>H3&nbsp;</small>
             <input type=checkbox name=h4 value=1><small>H4&nbsp;</small>
             <input type=checkbox name=h5 value=1><small>H5&nbsp;</small>
             <input type=checkbox name=h6 value=1><small>H6</small></td>
        </tr>
       </table>
    </td>
   </tr>
   <tr valign="top">
    <td><font size=6 color="#6666a7">&nbsp;3. </font></td>
    <td><font size=6>&nbsp;</font><input type=submit value="Analyze"></td>
   </tr>
  </table>
 </form>
 <hr>
 <p><strong>Description</strong><br><small>
  HTML Tag Analyzer (htaz) is a web-based HTML file analysis application. 
  It takes as input a directory name and examines each of the HTML, HTM, and 
  SHTML files in the directory and all subdirectories. This tool can be quite 
  useful on large sites that need a quick way to determine missing elements and 
  to check for consistency.</small>
 </p>
 <pre>The tags analyzed are
        &lt;TITLE&gt;         &lt;META&gt;
        &lt;LINK&gt;          &lt;H1&gt; &lt;H2&gt; .. &lt;H6&gt;

 The recognized &lt;meta&gt; tag attributes are
        Author          Keywords        Description     Expires 
        Copyright       Generator       Reply-to        Content-type
        All Meta Tags (even if not in list above)

 The recognized &lt;meta&gt; tag sub-attributes are:
        name            http-equiv      content         scheme
        lang            dir

 The recognized &lt;link&gt; tag attributes are
        rel             type            href            media
        charset         hreflang        rev             lang
        title           style           target          dir
        
 The contents of the &lt;title&gt; and &lt;h1&gt;..&lt;h6&gt; tags are also processed.
 </pre>
 <p><small>HTML Tag Analyzer is written in Perl 5. Some JavaScript is used in the "check
 all" and "clear all" buttons on the home page.</small></p>
 <p><small><em>Copyright &copy; 2000, <a href="http://www.horsburgh.com/">Horsburgh.com</a>.
 All Rights Reserved.</em></small></p>
 </body>
</html>
EOP
}

sub ReadParse {
  local (*in) = shift if @_;    # CGI input
  local ($meth, $errflag, $cmdflag);
	
  $meth = $ENV{'REQUEST_METHOD'};
  
  if (!defined $meth || $meth eq '' || $meth eq 'GET') {
    local ($key, $val, $i);
	
    if (!defined $meth || $meth eq '') {
      $in = $ENV{'QUERY_STRING'};
      $cmdflag = 1;
    } elsif($meth eq 'GET') {
      $in = $ENV{'QUERY_STRING'};
    } else {
      $errflag = 1;
    }

    @in = split(/[&;]/,$in); 
    push(@in, @ARGV) if $cmdflag;

    foreach $i (0 .. $#in) {
      $in[$i] =~ s/\+/ /g;

      ($key, $val) = split(/=/,$in[$i],2);

      $key =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
      $val =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;

      $in{$key} .= "\0" if (defined($in{$key}));
      $in{$key} .= $val;
    }

  } else {
    $errflag = 1;
  }

  return ($errflag ? undef : scalar(@in)); 
}

sub PrintHeader {
  return "Content-type: text/html\n\n";
}

# MyBaseUrl
# Returns the base URL to the script (i.e., no extra path or query string)
sub MyBaseUrl {
  local ($ret);
  $ret = 'http://' . $ENV{'HTTP_HOST'} . $ENV{'SCRIPT_NAME'};
  return $ret;
}


# MyFullUrl
# Returns the full URL to the script (i.e., with extra path or query string)
sub MyFullUrl {
  local ($ret);
  $ret = &MyBaseUrl() . $ENV{'PATH_INFO'} .
         (length ($ENV{'QUERY_STRING'}) ? "?$ENV{'QUERY_STRING'}" : '');
  return $ret;
}
