#!/usr/local/bin/perl5 # Name: html-include Author: Joe Smith 04-Dec-97 # Purpose: Includes subfiles into a non-parsed html page. # This avoids the overhead caused by x-server-parsed-html. $usage = < several lines that will be replaced with contents of include_dir/footer Each file that has any changes will be renamed to have a *.bak extension. The names of these *.bak files are sent to STDOUT so that they can be deleted if there are no errors. EOM chop($cwd = `pwd`); $include_dir = $_ = shift; # First arg is where to find the included files $include_abs = m%^/% ? $_ : "$cwd/$_"; # Absolute pathname die($usage) unless @ARGV; # Must have at least one more argument $error_count = 0; $| = 1; require "find.pl"; &find(@ARGV); # Call &wanted() for each file in directory exit($error_count ? 1 : 0); ############################################################################ sub wanted { # Called from &find with $name = "$dir/$_" $mtime = (stat $_)[9]; # File's modification time -f _ && /^.*\.(html|htm|shtml|sht)$/ && &process($_,$name); } $_ = $name; # For "perl -w" ($name is defined in find.pl) ############################################################################ sub process { # Process an HTML file local($file,$fullname) = @_; print STDERR "$fullname - "; open(IN,$file) || return(warn("can't read: $!\n")); $/ = ">"; # Allow for \n inside the tags @lines = ; close(IN); @output = (); $replacing = 0; # Nonzero when replacing old lines $changes = $includes = 0; foreach $line (@lines) { if ($line =~ //m) { &parse_args($1); # Look for 'file="name" back="x.html"' push(@output,$line); # Copy this line verbatim $replacing = 1; # But no other until html-include-end @old = (); $includes++; } elsif ($line =~ //m) { push(@old,$`); # Lines just before this directive $include_end = $&; $new = &include_file; # Use %args to locate file to include $old = join("",@old); # Usually starts and ends with "\n" $changes++ if $new ne $old; push(@output,$new,$include_end); # Replacement text $replacing = 0; } else { push(@output,$line) unless $replacing; push(@old,$line) if $replacing; } } if ($includes) { print STDERR ($changes == 1 ? "1 change" : "$changes changes"),"\n"; } else { print STDERR "no \n"; } return unless $changes; $oldf = "$file.bak"; $oldfullname = "$fullname.bak"; $newf = "$file.tmp"; if (open(OUT,">$newf") && print(OUT @output) && close(OUT)) { utime($mtime,$mtime+60,$newf); # Set file modification time unlink($oldf); # Remove .bak from last time rename($file,$oldf) || warn("Could not rename $file to $oldf: $!\n"); rename($newf,$file) || warn("Could not rename $newf to $file: $!\n"); print "$oldfullname\n"; # This file can be deleted } else { warn("Could not rewrite $file: $!\n"); $error_count++; } } ############################################################################ sub parse_args { # Search for key=val key="val" key='val' local($args) = @_; local($original) = $args; local($_); %args = (); while (($key,$_) = $args =~ /(\w+)=(.*)/) { ( /^"([^"]*)"\s*(.*)/ || /^'([^']*)'\s*(.*)/ || /(\S+)\s*(.*)/ ) && (($val,$_) = ($1,$2)); $args{$key} = $val; $args = $_; } $args{"file"} || warn("Could not find 'file=\"...\"' in $original\n"); } ############################################################################ sub include_file { # Include contents of file, with variable substitution local($inc_abs) = "$include_abs/" . $args{"file"}; local($inc_rel) = "$include_dir/" . $args{"file"}; unless($file_contents = $files{$inc_abs}) { if(open(INC,$inc_abs)) { local($/) = undef; $file_contents = "\n\t\n"; $file_contents .= ; # Read entire file as a single string $files{$inc_abs} = $file_contents; } else { warn("Could not read include file $inc_abs: $!\n"); } } $file_contents =~ s/\$(\w+)/$args{$1}/eg; # Insert args in result $file_contents; }