<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package Apache::SSI;
use Apache ();
use Apache::Options qw(&amp;OPT_EXECCGI); #for exec
use HTML::TreeBuilder ();
use HTTP::Date;
use File::Basename;

use vars qw($VERSION @ISA);

@ISA = qw(HTML::TreeBuilder);

#$Id: SSI.pm,v 1.14 1997/03/10 00:25:45 dougm Exp $
$VERSION = sprintf("%d.%02d", q$Revision: 1.14 $ =~ /(\d+)\.(\d+)/);

#wherever you choose:
#AddHandler perl-script .phtml

#add this to srm.conf:
#PerlModule Apache::SSI

#in access.conf or .htaccess say:
#PerlResponse Apache::SSI::handler

sub handler {
    my($r) = @_;
    %ENV = $r-&gt;cgi_env; #for exec
    $r-&gt;content_type("text/html"); 
    $r-&gt;send_http_header;
    my $p = Apache::SSI-&gt;new($r);
    $p-&gt;parse_file($r-&gt;filename);
    $r-&gt;print($p-&gt;as_HTML);
}

sub magic_type {
    my($self, $file) = @_;
    $file =~ /\.phtml$/; #temp hack for 'include' directive
}

sub find_file {
    my($self, $args) = @_;
    my($file,$virtual) = @{$args}{qw(file virtual)};
    my $ret;
    return if $file =~ /^\.\./;
    my $r = $self-&gt;{_r};
    my $base = dirname $r-&gt;filename;
    if($file !~ m,^/,,) {
	$ret = join "/", $base, $file;
    }
    return $ret if -e $ret;
    $r-&gt;log_error("Apache::SSI couldn't find file $to_parse $!");
    undef;
}

sub new {
    my($class, $r) = @_;
    my $self = $class-&gt;SUPER::new;
    $self-&gt;{_r} = $r;
    $self;
}

sub perlsub {
    my($self, $args) = @_;
    my $sub = $args-&gt;{sub};
    return defined &amp;{$sub} ? &amp;{$sub} : &amp;{"main\:\:$sub"};
}

sub comment {
    my($self, $comment) = @_;
    return unless $comment =~ s/^#//;
    $comment =~ s/\s*$//;
    my($action, $args) = split /\s+/, $comment, 2;
    $self-&gt;pos-&gt;push_content($self-&gt;$action({ split(/\s+|=/, $args) }));
}

sub echo {
    my($self, $args) = @_;
    my $r = $self-&gt;{_r};
    &amp;{"$args-&gt;{var}"}($r);
}

sub DATE_GMT { time2str; }
sub DATE_LOCAL { scalar localtime; }
sub DOCUMENT_NAME { basename $_[0]-&gt;filename; }
sub DOCUMENT_URI { $_[0]-&gt;uri; }
sub LAST_MODIFIED { lastmod($_[0]-&gt;filename); }

sub fsize { 
    my($self,$args) = @_;
    (stat($self-&gt;find_file($args)))[7]; 
}

sub lastmod {
    my($file) = @_;
    time2str((stat($file))[9]);
}

sub flastmod {
    my($self, $args) = @_;
    lastmod($args-&gt;{file} || $self-&gt;{_r}-&gt;filename);
}

sub exec {
    my($self, $args) = @_;
    #XXX did we check enough?
    my $r = $self-&gt;{_r};
    my $filename = $r-&gt;filename;
    unless($r-&gt;allow_options &amp; OPT_EXECCGI) {
	$r-&gt;log_error("httpd: exec used but not allowed in $filename");
	return "";
    }
    `$args-&gt;{cmd}`;
}

sub include {
    my($self, $args) = @_;
    my $r = $self-&gt;{_r};
    my $p = Apache::SSI-&gt;new($r);
    my $to_parse = $self-&gt;find_file($args);

    if($p-&gt;magic_type($to_parse)) {
	$p-&gt;parse_file($to_parse);
	return $p-&gt;as_HTML;
    }
    else {
	local *FH;
	open FH, $to_parse; # or $r-&gt;log_error
	return join '', &lt;FH&gt;; #eek
	#close FH;
    }
    undef;
}

sub config {
    "*** 'config' directive not implemented by Apache::SSI";
}

#test for perlsub directive
sub main::remote_host { $ENV{REMOTE_HOST}; }
sub main::env {
    join('', map {
	"$_ = $ENV{$_}\n";
    } keys %ENV);
}

1;

__END__

=head1 NAME

Apache::SSI - Implement Server Side Includes in Perl

=head1 SYNOPSIS

wherever you choose:

&lt;Files *.phtml&gt;
SetHandler perl-script
PerlHandler Apache::SSI
&lt;/Files&gt;

You may wish to subclass Apache::SSI for your own extentions

    package MySSI;
    use Apache::SSI ();
    @ISA = qw(Apache::SSI);

    #embedded syntax:
    #&lt;!--#something cmd=doit --&gt;
    sub something {
       my($self, $attr) = @_;
       my $cmd = $attr-&gt;{cmd};
       ...
       return $a_string;	   
    } 

=head1 DESCRIPTION

Apache::SSI implements the functionality of mod_include for handling
server-parsed html documents.
Each "command" or element is handled by an Apache::SSI method of the
same name.  attribute=value pairs are parsed and passed to the method
in an anonymous hash.

This module supports the same directives as mod_include, see it's 
documentation for commands and syntax.

In addition, Apache::SSI supports the following directives:

=item perlsub

This directive calls a perl subroutine:

 Hello user from &lt;!--#perlsub sub=remote_host --&gt;

=head1 CAVEATS

This module is not complete, it does not provide the full functionality 
of mod_include.  

There is no support for xssi directives.

=head1 SEE ALSO

For much more power, see the L&lt;HTML::Embperl&gt; and L&lt;Apache::ePerl&gt; modules. 

mod_include, mod_perl(3), HTML::TreeBuilder(3), Apache(3),
HTML::Embperl(3), Apache::ePerl(3)

=head1 AUTHOR

Doug MacEachern &lt;dougm@osf.org&gt;
</pre></body></html>