#   cgivar.pl - Some routines to build dynamic web pages
#   Copyright (c) 1997  Martin Schulze <joey@infodrom.north.de>

#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.

#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

my %cgivar_head = ();
my %cgivar_entry = ();
my %cgivar_foot = ();

# Load a template file
#
# [0] is the filename
#
sub cgivar_load
{
    my $fname = $_[0];
    my $text;

    if (open(F,$fname)) {
	$text = "";
	do {
	    if (!eof(F)) {
		$_ = <F>;
		$text .= $_ if (!/<!-- Begin Entry -->/i);
	    }
	} until (/<!-- Begin Entry -->/i || eof(F));
	$cgivar_head{$fname} = $text;

	# Skip this line
	$text = "";
	do {
	    if (!eof(F)) {
		$_ = <F>;
		$text .= $_ if (!/<!-- End Entry -->/i);
	    }
	} until (/<!-- End Entry -->/i || eof(F));
	$cgivar_entry{$fname} = $text;

	# Skip this line
	$text = "";
	while (<F>) {
	    $text .= $_;
	};
	$cgivar_foot{$fname} = $text;

	close (F);
    }
#    print "<HEAD>\n" . $cgivar_head{$fname}. "</HEAD>\n";
#    print "<ENTRY>\n" . $cgivar_entry{$fname} . "</ENTRY>\n";
#    print "<FOOT>\n" . $cgivar_foot{$fname} . "</FOOT>\n";
}

sub cgivar_help
{
    my $text;

    $text = "<h1>Documentation for cgivar.pl</h1>\n\n";
    $text .= "This library is Copyright (c) 1998 by Martin Schulze &lt;joey\@infodrom.north.de&gt;<p>\n\n";
    $text .= "<blockquote>\n";
    $text .= "It consists of a bunch of routines to work "
	. "with templates of html files.";
    $text .= "<ul>\n";
    $text .= "<li> cgivar_load(filename)<br>\n";
    $text .= "<li> cgivar_help()\n";
    $text .= "<li> cgivar_eval_head(filename,%variables)\n";
    $text .= "<li> cgivar_eval_entry(filename,%variables)\n";
    $text .= "<li> cgivar_eval_foot(filename,%variables)\n";
    $text .= "</ul>\n\n";
    $text .= "Once a template file is loaded it is stored internally\n"
	. "and doesn't need to be loaded again.  The template is splitted\n"
        . "into three parts: a header, a entry that might be repeated and\n"
        . "a footer.  The sections are divided by a special comment\n"
	. "&lt;!-- Begin Entry --&gt; and &lt;!-- End Entry --&gt; (case\n"
	. "insensitive).  To evaluate either of them you just have to call one\n"
        . "of the cgivar_eval_* routines with the name of the already loaded\n"
	. "template file and a hash table that contains name=value bindings\n"
	. "of the referenced variables. <p>\n\n"
	. "The template file may consist of some pseudo html code to reference\n"
	. "variables that will be replaced by its values when the section will\n"
	. "be evaluated.  Each of this looks like <strong>&lt;cgivar name arguments&gt;</strong>.\n"
	. "This would replace the whole statement with the value of the variable called\n"
	. "<em>name</em>.  Some variables understand arguments and there are some\n"
	. "internal variables, too.\n\n";
    $text .= "<ul>\n"
	. "<li> Any variable<br>\n"
	. "     You may add <strong>modify=p</strong> as argument if you want\n"
	. "     empty lines be replaced by a new paragraph (&lt;p&gt;).\n"
	. "<li> internal-today<br>\n"
	. "     This will add the actual date - in german manner.\n"
	. "     Anybody to step forward and implement something like\n"
	. "     format=\"dd/mm/yy\"?\n"
	. "<li> internal-back<br>\n"
	. "     This will add an href.  You may specify <strong>title=\"string\"</strong>\n"
	. "     as the title for the link and <strong>default=\"string\"</strong> as\n"
	. "     link that should be used if the library isn't able to determine from\n"
	. "     which page the user came.  The link will be completely left out if neither\n"
	. "     a Referer nor a default is given.  If an <strong>img=\"string\"</strong>\n"
	. "     is given the link will be placed around the image, with <strong>border=0</strong>.\n"
	. "<li> internal-hidden<br>\n"
	. "     This will print a list of all variables as hidden input fields.\n"
	. "     It is designed to help with some kind of forms.\n"
	. "</ul>\n\n";
    $text .= "<h3>Example</h3>\n\n";
    $text .= "<pre>\n"
	. "&lt;html&gt;\n"
	. "&lt;head&gt;&lt;title&gt;Some test&lt;/title&gt;&lt;/head&gt;\n\n"
	. "&lt;body&gt;\n"
	. "&lt;h1&gt;This is a test for cgivar.pl&lt;/h1&gt;\n\n"
	. "&lt;!-- Begin Entry --&gt;\n"
	. "&lt;b&gt;&lt;cgivar myvar&gt;&lt;/b&gt;&lt;br&gt;\n"
	. "&lt;!-- end entry --&gt;\n\n"
	. "&lt;cgivar internal-back title=\"Back\"&gt;\n"
	. "&lt;hr&gt;&lt;address&gt;&#169; &lt;a href=\"http://www.north.de/~joey/finger.html\"&gt;Joey&lt;/a&gt;, &lt;cgivar internal-today&gt;&lt;/address&gt;\n"
	. "&lt;/body&gt;\n"
	. "&lt;/html&gt;\n"
	. "</pre>\n\n";

    $text .= "</blockquote>\n";

    return $text;
}

# Internal routine that interprets some template and hashes
#
# [0] html template
# [1] hash containing variables
sub cgivar_eval
{
    my $text = shift;
    my @text = split(/\n/,$text);
    my $x = shift;
    my %var = %$x;
    my $key;
    my $result = "";
    my @date;
    my $name,$args,$remainder;
    my $title;
    my $default;
    my $img;
    my $modify;
    my $myvar;

    foreach $_ (@text) {
	if (/(.*)<cgivar ([^> ]+)([^>]*)>(.*)/i) {
	    $name = $2;
	    $args = $3;
	    $remainder = $4;
	    $result .= $1;
	    if ($name eq "internal-hidden") {
		foreach $key (keys(%var)) {
		    $result .= sprintf ("<input type=hidden size=0 name=\"%s\" value=\"%s\">\n",$key, join(' ',$var{$key}));
		}
	    } elsif ($name eq "internal-back") {
		$title = "Back";
		$default = $img = "";
		$title = $1 if ($args =~ /title="([^"]+)"/);
		$default = $1 if ($args =~ /default="([^"]+)"/);
		$img = $1 if ($args =~ /img="([^"]+)"/);

		if (defined($ENV{'HTTP_REFERER'})) {
		    if ($img) {
			$result .= sprintf ("<a href=\"%s\"><img src=\"%s\" border=0 alt=\"%s\"></a>",
			    $ENV{'HTTP_REFERER'}, $img, $title);
		    } else {
			$result .= sprintf ("<a href=\"%s\">%s</a>", $ENV{'HTTP_REFERER'}, $title);
		    }
		} else {
		    if ($default) {
			if ($img) {
			    $result .= sprintf ("<a href=\"%s\"><img src=\"%s\" border=0 alt=\"%s\"></a>", $default, $img, $title);
			} else {
			    $result .= sprintf ("<a href=\"%s\"></a>", $default, $title);
			}
		    }
		}

	    } elsif ($name eq "internal-today") {
		@date = localtime();
		$result .= sprintf ("%d %s '%d", $date[3], 
				    ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$date[4]],
				    $date[5]);
		
#	    } elsif ($name eq "error") {
#		print $cgierror if ($cgierror);
	    } else {
		$modify = "";
		$modify = $1 if ($args =~ /modify=([^ ]+)/);
		if ($modify eq "p") {
		    $myvar = $var{$name};
		    $myvar =~ s/\r?\n\r?\n/<p>\n/g;
		    $result .= $myvar
		} else {
		    $result .= $var{$name};
		}
	    }
	    $result .= $remainder;
	} else {
	    $result .= $_;
	}
	$result .= "\n";
    }
    return $result;
}

# Evaluate the head of a template and return the results
#
# [0] filename of template
# [1] %hash of variables
#
sub cgivar_eval_head
{
    my $fname = shift;
    my $x = shift;
    my %var = %$x;

    &cgivar_load($fname) if (!defined($cgivar_head{$fname}));

    return &cgivar_eval($cgivar_head{$fname}, \%var);
}

# Evaluate the regular entry of a template and return the results
#
# [0] filename of template
# [1] %hash of variables
#
sub cgivar_eval_entry
{
    my $fname = shift;
    my $x = shift;
    my %var = %$x;

    return "" if (!defined($cgivar_entry{$fname}));

    return &cgivar_eval($cgivar_entry{$fname}, \%var);
}

# Evaluate the foot of a template and return the results
#
# [0] filename of template
# [1] %hash of variables
#
sub cgivar_eval_foot
{
    my $fname = shift;
    my $x = shift;
    my %var = %$x;

    return "" if (!defined($cgivar_foot{$fname}));

    return &cgivar_eval($cgivar_foot{$fname}, \%var);
}

# Make perl happy
1;
