#!/usr/bin/perl -w 
use warnings;

# Main program --------------------------------------------------------------------------------------
$verbose = 1;                                                  # Lots of messages?
$masterd = "/afs/cc.lehigh.edu/home/inlts2/public/newcore";    # Location of frameset source file?
$masterf = "frame.html";                                       # Name of frameset source file?
$here = ".";                                                   # What directory to start with?

$master = $masterd . "/" . $masterf;                           # Source file path
$mastertext = "";                                              # Source file contents
$level = 0;                                                    # Traversal depth

header () if ($verbose);                                       # Print the header
traverse ($here);                                              # Walk the tree...
exit 0;                                                        # ...and we're done.

# Subroutines ---------------------------------------------------------------------------------------

# HEADER: Explanatory header
sub header {

   print "LTS website conversion script\n\n";
   print "'Target' files are pairs of files with a common name. These should\n";
   print "correspond to pages created in accordance with the previous web site design.\n"; 
   print "One file is a frameset file, with an 'html' extension; the other is a content\n";
   print "frame file, with an 'shtml' extension.\n\n";
   print "'Orphan' files are other (unpaired) files with HTML content.\n\n";
   print "The following flag characters are used to indicate the properties of pages:\n";
   print "B - The page does NOT have a base target set to top.\n";
   print "D - The page does NOT have a DOCTYPE declaration.\n";
   print "G - The page has a 'generator' meta element.\n";
   print "L - The page embeds the LTS logo (probable 'pseudo-frame' page).\n";
   print "M - The page contains Microsoft XML info (Word/Publisher/etc).\n";
   print "S - The page contains nonstandard (non-LTS) style information.\n";
   print "T - The page uses or is a Dreamweaver template (possible Contribute page).\n\n";
   print "================================================================================\n\n";
   
   return 1;
   }

# GETPAGE: read a file
sub getpage {

   my $filename = shift @_;             # File to read
   my $filetext = "";                   # Buffer for entire file

   # Read the file   
   open (IPAGE, "<$filename")           or die "PROBLEM: Unable to open file $filename ($!).\n";   
   {
      local $/;                         # Bypass line-by-line processing
      $filetext = <IPAGE>;              # Read the entire file in one go
      } 
   close (IPAGE);                       # No reason to keep it open any longer

   return $filetext; 
   }

# PUTPAGE: write a file
sub putpage {

   my $filename = shift @_;             # File to write
   my $filetext = shift @_;             # File contents
   
   open (OPAGE, ">$filename")           or die "PROBLEM: Unable to create file $filename ($!).\n";
   {
      local $/;                         # Don't add end-of-line
	  print (OPAGE $filetext)           or die "PROBLEM: Unable to write file $filename ($!).\n";
      }
   close (OPAGE);                       # No reason to keep it open any longer
   
   return 1;
   }

# GETTITLE: find the document title   
sub gettitle {

   my $target = shift @_;               # Base name of target pair
   my $filetext = "";                   # File text buffer
   my $dtitle = "LTS: Untitled page $target.html";   
   

   # See if the framset page has a nondefault title   
   $filetext = getpage ($target . ".html");
   if (($filetext =~ m{<title>([^<]*)</title>}i) &&
      ($1 !~ m{^lts:\s+library (?:and|&amp;)\s+(?:technical|technology)\s+services\s+\(lts\)}i))
      {return $1;}  

   # See if the content page has a nondefault title   
   $filetext = getpage ($target . ".shtml");
   if (($filetext =~ m{<title>([^<]*)</title>}i) &&
      ($1 !~ m{^lts:\s+library (?:and|&amp;)\s+(?:technical|technology)\s+services\s+\(lts\)}i))
      {return $1;}  

   # Otherwise return the default title
   return $dtitle;   
   }    
   
# REPLACE: create new frameset 
sub replace {

   my $target = shift @_;               # Base name of target pair
   my $copytext = "";                   # Copy of frameset file
   my $title = "";                      # Page title
   
   my $new = $target . ".html";         # Name of frameset file
   my $old = $target . ".pre-rd";       # Name of backup file
   
   # Get the title
   $title = gettitle ($target);

   # Back up the original frameset file
   rename ($new, $old)                  or die "PROBLEM: Unable to rename file $new as $old ($!).\n";

   # Read the source file if needed
   $mastertext = getpage ($master) unless ($mastertext);
   
   # Copy and modify the template
   $copytext = $mastertext;
   $copytext =~ s/##NAME##/$target/gs;
   $copytext =~ s/##TITLE##/$title/gs;

   # Write the new frameset file
   putpage ($new, $copytext);   

   return 1;
   }

# ANALYZE: look for key features in pages
sub analyze {

   my $filename = shift @_;             # File to examine
   my $attrs = "";                      # Attribute string to be built
   my $filetext = "";                   # Buffer for entire file

   # Grab the file  
   $filetext = getpage ($filename);   
   
   # Perform tests
   if ($filetext !~ m{<(?:base)\s+(?:target)\s*=\s*(?:"_top")}is)         
      {$attrs .= "B";}                  # Page does not have base target set to top
   if ($filetext !~ m{<!doctype\s+html}is)
      {$attrs .= "D";}                  # Page has no DOCTYPE declaration
   if ($filetext =~ m{<(?:meta)\s+(?:name)\s*=\s*(?:"generator")}is)
      {$attrs .= "G";}                  # Page has a "generator" meta element
   if ($filetext =~ m{<(?i:img)\s+[^>]*(?i:src=)".*/lts/ltslogo-s\.gif"}s)         
      {$attrs .= "L";}                  # Page embeds LTS logo
   if ($filetext =~ m{urn:schemas-microsoft\.com}is)
      {$attrs .= "M";}                  # Page has Microsoft cruft (Word/Publisher/etc)
   my @stylinks = $filetext =~ m{<(?:link|LINK)\s+(?:[^>]*)(?:type|TYPE)\s*=\s*"text/css"\s+(?:[^>]*)}s;
   my $numslinks = scalar (@stylinks);
   if ((($filetext !~ m{(?:href|HREF)\s*=\s*".*/lts/master\.css"}s) && ($numslinks > 0)) ||
      ($numslinks > 1) || ($filetext =~ m{<(?:style|STYLE)\s+(?:type|TYPE)\s*=\s*"text/css"}s))	  
      {$attrs .= "S";}                  # Page has nonstandard style info
   if ($filetext =~ m{<!--\s+(?:#|template|instance)begineditable}is)         
      {$attrs .= "T";}                  # Page uses Dreamweaver template
   
   return $attrs;
   }

# TRAVERSE: breadth-first traversal of directory tree
sub traverse {
   
   my $dirname = shift @_;              # Directory to traverse
   my @targets = ();                    # Paired frameset/content files
   my @orphans = ();                    # Other HTML files
   my @subdirs = ();                    # Directories within this one
   $level++;                            # Keep track of depth
   my $indent = "   " x $level;         # Indent report
   
   # Read the directory
   opendir (DIR, $dirname)              or die "PROBLEM: Unable to open directory $dirname ($!).\n";
   chdir ($dirname)                     or die "PROBLEM: Unable to change directory to $dirname.\n";
   my $pathname = `/bin/pwd`;
   print "$indent Level $level: Scanning directory $dirname ($pathname) ...\n";
   my @entries = sort readdir(DIR);

   # Process each entry
   ENTRY: foreach $entry (@entries) {
 
      # Ignore symlinks and other special files 
      next ENTRY if (-l $entry);	  
      next ENTRY unless (-f $entry || -d $entry);

      # Capture subdirectories (ignore . and ..)
      if ((-d $entry) && ($entry !~ /^\.{1,2}$/)) {
         push @subdirs, $entry;
         next ENTRY;
         }

      # Capture probable framesets
      elsif (($entry =~ /^(.+)\.html$/) && (-e "$1.shtml")) { 
         push @targets, $1; 
         next ENTRY;
         }
  
      # Skip content pages associated with a frameset
      elsif (($entry =~ /^(.+)\.shtml$/) && (-e "$1.html")) { 
         next ENTRY;
         }

      # Capture other HTML files
      elsif ($entry =~ /^(.*)\.[sS]?[hH][tT][mM][lL]?$/) { 
         push @orphans, $entry;
         next ENTRY;
         }

      # Ignore images, media, stylesheets, and so on
      else {
         next ENTRY;
         }

      }

   # Report on the files found at this level
   my $n_targets = scalar (@targets);   # Number of target pairs found
   my $n_orphans = scalar (@orphans);   # Number of orphan files found
   my $n_subdirs = scalar (@subdirs);   # Number of subdirectories at this level
   print "$indent At this level: $n_targets target pairs; $n_orphans other HTML pages; $n_subdirs subdirectories.\n";  
   if ($verbose) {
      foreach $target (@targets) { 
	     my $flags = analyze ($target . ".shtml"); 
		 print "   $indent Target: $target.html and $target.shtml ...$flags\n"; 
		 }
	  print "   $indent           -----\n" if ($n_targets > 0);
      foreach $orphan (@orphans) { 
	     my $flags = analyze ($orphan); 
		 print "   $indent Orphan: $orphan  ...$flags\n"; 
		 } 
	  print "   $indent           -----\n" if ($n_orphans > 0);
	  foreach $subdir (@subdirs) { 
	     print "   $indent Subdir: $subdir  ...\n";  
		 } 
	  print "\n";
      }	  

   # Convert the target files
   foreach $target (@targets) {replace ($target);}
	  
   # Now traverse the subdirectories recursively
   my $s_targets = 0;                   # Number of targets below this level
   my $s_orphans = 0;                   # Number of orphans below this level 
   my $s_subdirs = 0;                   # Number of subdirectories below this level
   foreach $subdir (@subdirs) {      
      ($t, $o, $d) = traverse ($subdir);  
	  $s_targets += $t;
	  $s_orphans += $o;
	  $s_subdirs += $d;
      }
	  
   # Calculate the cumulative counts
   $n_targets += $s_targets;
   $n_orphans += $s_orphans;
   $n_subdirs += $s_subdirs;   
   print "$indent Level $level: Total for $dirname and its $n_subdirs subdirectories: $n_targets target pairs; $n_orphans other HTML files.\n";

   # Restore original directory
   chdir ("..")                         or warn "PROBLEM: Unable to restore directory.\n";

   $level--;     # undent
   
   # Report counts to next higher level incarnation
   return ($n_targets, $n_orphans, $n_subdirs);
   }