home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
bos224d6.zip
/
perlssi
< prev
next >
Wrap
Text File
|
1999-11-17
|
15KB
|
403 lines
#! /usr/bin/perl
#
# Name: perlssi
# Title: Implementation of SSI as a Perl filter
# Package: Xitami web server
#
# Written: 96/11/02 Xitami team <xitami@imatix.com>
# Revised: 99/06/07 Xitami team <xitami@imatix.com>
#
# Copyright: Copyright (c) 1991-99 iMatix
# License: This is free software; you can redistribute it and/or modify
# it under the terms of the License Agreement as provided
# in the file LICENSE.TXT. This software is distributed in
# the hope that it will be useful, but without any warranty.
#
# This program is based on the FakeSSI program, documented at:
# <URL:http://sw.cse.bris.ac.uk/WebTools/fakessi.html>
#
# Server side include documentation at NCSA:
# <URL:http://hoohoo.ncsa.uiuc.edu/docs/tutorials/includes.html>
#
# In defaults.cfg:
# [Filter]
# shtml=perlssi # Parse files with .shtml extension
#
# This script is a quick and dirty SSI solution, not meant to be used for
# heavy work, but at least something until we build SSI into Xitami the
# proper way. It's also a useful demo of a filter program.
#
require 5;
$BINDIR = $ENV {CGI_ROOT}; # Location of CGI programs
$BINURL = $ENV {CGI_URL}; # CGI URL prefix
$DOCROOT = $ENV {DOCUMENT_ROOT}; # Location of web pages
$DOCPATH = $ENV {PATH_TRANSLATED}; # Document root, cut before '/'
$DOCPATH = $1 if $DOCPATH =~ /(.*)\//;
$errno = 0;
# Set the default error message you want, the size format, time format and
# timezone here.
$errmsg = '<P>[perlssi: "#%s" produced errors]';
$sizefmt = 'bytes';
# Default time format: eg Mon, 05-Jan-98 15:25:05 NZST
$timefmt = "%A, %d-%b-%y %H:%M:%S %Z";
$timezone = $ENV {'TZ'};
$timezone = "" if (!defined($timezone)); # Empty if not set
@timezones = split(/-?\d+/, $timezone); # Get Timezones
if (defined($timezones[0]) && (!defined($timezones[1])))
{ $timezones[1] = $timezones[0]; }
@DAYS_OF_WEEK = ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday');
@MONTH_NAME = ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December');
# OK, now to work!!!
print ("Content-type: text/html\n\n");
# Convert the target file name from WWW form into explicit form
$sent = $ENV {SCRIPT_NAME};
$ENV {'HTTP_REFERER'} = $sent
unless $ENV {'HTTP_REFERER'};
$infile = $sent;
&MakePathname;
$target = $outfile;
# Read in target WWW page, and make into one long line.
$bigline = join ('', <STDIN>);
# Go thru the line until we reach the end, looking for SSI's.
$len = length ($bigline);
while ($len > 0) {
if ($bigline =~ /<!--\s*#\s*/) {
print ($`);
if ($' =~ /-->/) {
$ssi = $`;
$bigline = $';
&HandleSSI;
$len = length ($bigline);
}
}
else {
$len = 0;
print ($bigline);
}
}
0; # Return code 0 -> everything okay
#----------------------------------------------------------------------
sub HandleSSI {
if ($ssi =~ /^config/i) {
@var1 = split ('="', $ssi);
@var2 = split ('"', $var1 [1]);
$var = $var2 [0];
if ($ssi =~ /errmsg/i) {
$errmsg = $var;
}
elsif ($ssi =~ /sizefmt/i) {
$sizefmt = $var;
}
elsif ($ssi =~ /timefmt/i) {
$timefmt = $var;
}
else {
print "<P>Unrecognised #config variable";
&GiveErrMsg;
}
}
elsif ($ssi =~ /^echo\s+var="([^"]+)"/i) {
$var = $1;
if ($var eq "DOCUMENT_NAME") {
@output = split ('/', substr ($target, rindex ($target, '/')));
print ($output [1]);
}
elsif ($var eq "DOCUMENT_URI") {
print $sent;
}
elsif ($var eq "DATE_GMT") {
&strftime (time (), 0);
}
elsif ($var eq "DATE_LOCAL") {
&strftime (time (), 1);
}
elsif ($var eq "LAST_MODIFIED") {
&strftime ( (stat ($target))[9], 1);
}
elsif ($ENV {$var}) {
print $ENV {$var};
}
else {
print "<P>Unrecognised #echo variable: $var";
&GiveErrMsg;
}
}
elsif ($ssi =~ /^exec/i) {
if ($ssi =~ /cgi="([^"?]+)(\??([^"]*))"/i) {
$infile = $1;
$args = $3;
&MakePathname;
$var = $outfile;
if ($errno == 0) {
# We can now execute the CGI script in $var
$ENV {"QUERY_STRING"} = $3;
# First, handle MS-DOS systems
if (defined ($ENV {"COMSPEC"})) {
$var =~ s/\//\\/g;
# Try normal executable programs first
if ($var =~ /\.exe$|\.com$|\.bat$/i) {
$_ = `$var $args`;
}
else {
# Check file header to see if it's a script
# We're looking for '#! xxxx' or '/*! xxxx'
open (FOO, $var);
$_ = <FOO>;
chop;
close (FOO);
if (/^\#\!\s*(.+)|^\/\*\!\s*([^*]+)\*\//) {
$_ = `$1 "$var" $args`;
}
else {
print "<P>Cannot execute $var";
&GiveErrMsg;
}
}
}
# Handle other systems (OS/2 may need to be handled as DOS)
else {
$_ = `$var $args`;
}
# If output has HTTP header fields, skip to blank line
if (/^[A-Z-]+: /i) {
/\n\n/;
print $';
}
else {
print $_;
}
}
}
elsif ($ssi =~ /cmd="([^"]+)"/i) {
print `$1`;
}
else {
print "<P>#exec command not understood";
&GiveErrMsg;
}
}
elsif ($ssi =~ /^include/i) {
&WhichFile;
if ($errno == 0) {
open (FOO, $filename);
$bigline = join ('', <FOO>).$bigline;
close (FOO);
}
else {
print "<P>#include file not found: $filename";
&GiveErrMsg;
}
}
elsif ($ssi =~ /^flastmod/i) {
&WhichFile;
if ($errno == 0) {
&strftime ((stat ($filename))[9], 1);
}
else {
print "<P>#flastmod file not found: $filename";
&GiveErrMsg;
}
}
elsif ($ssi =~ /^fsize/i) {
&WhichFile;
if ($errno == 0) {
$size = -s $filename;
if ($sizefmt =~ /abbrev/i) {
print (int ( ($size / 1024) + 1), "Kbytes");
}
else {
print ("$size bytes");
}
}
else {
print "<P>#fsize file not found: $filename";
&GiveErrMsg;
}
}
else {
print "<P>Unrecognised SSI command";
&GiveErrMsg;
}
}
sub MakePathname {
$errno = 1;
$info = $infile;
if ($info =~ /^$BINURL\//) {
@split1 = split (/$BINURL\//, $info);
$info = join ('/', $BINDIR, $split1 [1]);
}
else {
$info = $DOCROOT.$info;
}
$outfile = $info;
if (!-e $outfile) {
print "<P>File not found: $outfile";
&GiveErrMsg;
}
else {
$errno = 0;
}
}
sub GiveErrMsg {
printf ($errmsg, $ssi);
}
sub WhichFile {
$errno = 1;
if ($ssi =~ /virtual="\/?([^"]+)"/i) {
$filename = "$DOCROOT/$1";
}
elsif ($ssi =~ /file="([^"]+)"/i) {
# If the SSI is a "#include file=", then prepend the filename
# with the invoking document's absolute path - DH 98/06/20
$filename = "$DOCPATH/$1";
}
if (-e $filename) {
$errno = 0;
}
}
# Usage:
# strftime ( seconds-since-epoch, local-flag )
#
# Where local-flag is 0 for GMT
# and 1 for local time
#
# Defaults to: current time, and local time format
#
# Display the time specified as either a GMT time string, or a local time
# string in the format specified by the global variable $timefmt, using
# the time zone in $timezone.
sub strftime {
local ($nowtime, $timetype) = @_;
$nowtime = time() if (! defined($nowtime));
$timetype = 1 if (! defined($timetype));
defined($timefmt) || ($timefmt = "%A, %d-%b-%y %H:%M:%S %Z");
if ($timetype == 0) {
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= gmtime ($nowtime);
}
else {
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= localtime ($nowtime);
}
# Setup day and month names, and year, for later use.
$lday = $DAYS_OF_WEEK[$wday];
$lmon = $MONTH_NAME[$mon];
$year += 1900; # Add in offset to get 4 digit year
defined($lday) || ($lday = "");
defined($lmon) || ($lmon = "");
local ($i) = (0, "");
for ($i = 0; $i < length($timefmt); $i++)
{
if (substr($timefmt, $i, 1) eq "%")
{ # A magic value in the format string, expand the item
$i++; # Skip the percent
local ($pad) = "02"; # Pad with "0" by default
if (substr($timefmt, $i, 1) eq "-") {$i++; $pad = ""} # No padding
if (substr($timefmt, $i, 1) eq "_") {$i++; $pad = "2"} # Pad with spaces
local ($ch) = substr($timefmt, $i, 1); # Format character
# Poor man's switch:
# The recognised symbols are the ones recognised by GNU date.
# Ideally these would be defined into a table of subroutines to
# call, but I'll have to check if Perl 4 can handle references to
# subroutines.
# symbols
$ch eq "%" && do { print "%"; next; };
$ch eq "n" && do { print "\n"; next; };
$ch eq "t" && do { print "\t"; next; };
# Time format fields
$ch eq "H" && do { printf("%${pad}d", $hour); next; };
$ch eq "I" && do { printf("%${pad}d", ($hour % 12) +1); next; };
$ch eq "k" && do { printf("%2d", $hour); next; };
$ch eq "l" && do { printf("%2d", ($hour % 12) +1); next; };
$ch eq "M" && do { printf("%${pad}d", $min); next; };
$ch eq "p" && do { print ($hour < 12 ? "AM" : "PM"); next; };
$ch eq "r" && do { printf("%${pad}d:%${pad}d:%${pad}d %s",
(($hour % 12) + 1), $min, $sec,
($hour < 12 ? "AM" : "PM")); next; };
$ch eq "s" && do { print $nowtime; next; };
$ch eq "S" && do { printf("%${pad}d", $sec); next; };
$ch eq "T" && do { printf("%${pad}d:%${pad}d:%${pad}d",
$hour, $min, $sec); next; };
# This one is supposed to be the locale's time format, but
# we'll just have to have military time for now.
$ch eq "X" && do { printf("%${pad}d:%${pad}d:%${pad}d",
$hour, $min, $sec); next; };
$ch eq "Z" && do { print ($timetype? ($timezones[$isdst ? 1 : 0])
: "GMT"); next; };
# Date format fields
$ch eq "a" && do { print substr($lday, 0, 3); next; };
$ch eq "A" && do { print $lday; next; };
$ch eq "b" && do { print substr($lmon, 0, 3); next; };
$ch eq "B" && do { print $lmon; next; };
# This one works only with perl 5; we'd have to emulate it in
# perl 4. Prints out the time like ctime().
$ch eq "c" && do { print scalar localtime($nowtime); next; };
$ch eq "d" && do { printf("%${pad}d", $mday); next; };
$ch eq "D" && do { printf("%${pad}d/%${pad}d/%${pad}d",
$mday, ($mon + 1), ($year % 100));next; };
$ch eq "h" && do { print substr($lmon, 0, 3); next; };
$ch eq "j" && do { local ($pd) = $pad; $pd =~ s/2/3/;
printf("%${pd}d", $yday); next; };
$ch eq "m" && do { printf("%${pad}d", ($mon + 1)); next; };
# This should be week number of year with Sunday as first day of
# the week, but we cheat and just go mod 7, for now.
$ch eq "U" && do { printf("%${pad}d", int($lday / 7)); next; };
$ch eq "w" && do { print $wday; next; };
# This should be week number of year with Monday as first day of
# the week, but we cheat and just go mod 7, for now.
$ch eq "W" && do { printf("%${pad}d", int($lday / 7)); next; };
# This is supposed to be the locale's time format, but we cheat
# and just print mm/dd/yy for now.
$ch eq "x" && do { printf("%${pad}d/%${pad}d/%${pad}d",
($mon + 1), $mday, ($year % 100));next; };
$ch eq "y" && do { printf("%${pad}d", ($year % 100)); next; };
$ch eq "Y" && do { local ($pd) = $pad; $pd =~ s/2/4/;
printf("%${pd}d", $year); next; };
# If we fall through this far, then it wasn't matched so we'll
# print it out literally.
print "%" . ($pad ne "02" ? ($pad eq "2" ? "_" : "-") : "") . $ch;
} # Twas a magic code
else
{ # Not a magic code, print literally
print substr($timefmt, $i, 1);
}
}
}