#!/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;
}