package TripodPage;

#################
# TripodPage.pm #
##############################################################################
# TripodPage is a module that makes it easier for you to generate dynamic    #
# pages from your scripts.  TripodPage does two big things for you:          #
#                                                                            #
#   1. It generates an HTTP header for you, so you don't have to go to the   #
#      trouble of outputting a 'Content-Type:  text/html\n\n' or all that    #
#      other stuff.  This is especially helpful if, like a lot of people,    #
#      you don't know what an HTTP header is supposed to look like!          #
#   2. It lets you take an HTML template and fill in certain values that you #
#      want to be dynamic.  For example, if you wanted your script to output #
#      a page that always showed the current time, you could do that easily  #
#      with TripodPage.                                                      #
#                                                                            #
# The functions you care about are:                                          #
#                                                                            #
#    * sendPage();                                                           #
#    * sendNonCachedPage();                                                  #
#    * printHeader();                                                        #
#                                                                            #
# sendPage() is the most important one.  sendPage() takes an html file,      #
# in any variables that it contains, and spits the page out to the web       #
# server.  It takes two arguments; the first is the location of the html     #
# file, and the second is a reference to a hash of variables.  If you aren't #
# familiar with hashes or with variables, just follow the example and you    #
# should do fine.  Here's the example - this one's long, with a couple of    #
# parts to it:                                                               #
#                                                                            #
#   $page_location = 'example.html';                                         #
#   $variable_hash{timezone} = $ENV{TZ};                                     #
#   $variable_hash{ip_address} = $ENV{REMOTE_HOST};                          #
#   $variable_hash{browser} = $ENV{HTTP_USER_AGENT};                         #
#   $PAGE->sendPage($page_location, \%variable_hash);                        #
#   exit;                                                                    #
#                                                                            #
# The 'example.html' file referred to at the beginning might look something  #
# like this:                                                                 #
#                                                                            #
#   <HTML>                                                                   #
#   <HEAD><TITLE>Example Page</TITLE></HEAD>                                 #
#   <BODY BGCOLOR="#FFFFFF">                                                 #
#   <H3>Example Page</H3>                                                    #
#   You are coming in from this timezone: $timezone <BR>                     #
#   You are using the $browser browser.  Your ip address is $ip_address.     #
#   </BODY></HTML>                                                           #
#                                                                            #
# Together, this script and html file will output a page that shows the      #
# viewer's browser, ip address, and timezone.  First, the script specifies   #
# the name of the html file that we will be using.  Second, it creates a     #
# hash which contains all the variables contained within the page - in this  #
# case, 'timezone', 'ip_address', and 'browser' - and assigns values to each #
# of them.  Note that in this case it is getting the values out of a special #
# hash called %ENV, which contains environment variables that all CGI        #
# scripts have access to, but you could have different variables that get    #
# their values from other places, like random numbers, the time or date,     #
# input from a form, etc.  Finally, the script calls sendPage() to take the  #
# html file and fill in the variables with the contents of the hash.         #
# sendPage() looks at the html and searches for words preceded by dollar     #
# signs.  In our example file, it finds $timezone, $browser, and             #
# $ip_address.  Each of these then gets replaced by the values from the      #
# hash.  So the output might look something like this:                       #
#                                                                            #
#   <HTML>                                                                   #
#   <HEAD><TITLE>Example Page</TITLE></HEAD>                                 #
#   <BODY BGCOLOR="#FFFFFF">                                                 #
#   <H3>Example Page</H3>                                                    #
#   You are coming in from this timezone: US/Eastern <BR>                    #
#   You are using the Mozilla/4.61 [en] (Win98; U) browser.  Your ip address #
#   is 208.7.131.186.                                                        #
#   </BODY></HTML>                                                           #
#                                                                            #
# That's what you'd see if you were using my personal computer at Tripod -   #
# you'd see something quite different.  This is what's cool about            #
# sendPage() - it lets you present different information in your page under  #
# different circumstances.                                                   #
#                                                                            #
# We can go over the last two functions quickly.  sendNonCachedPage() works  #
# just like sendPage(), except that it also tells the browser not to cache   #
# the page that is sent.  This is a good idea if the information you are     #
# sending back changes from moment to moment, and you want to make sure that #
# a visitor who reloads the page always gets the newest information.         #
#                                                                            #
# printHeader() just outputs the HTTP header that tells the browser you are  #
# outputting an HTML page from your script.  If your script is outputting    #
# something besides HTML, you can also pass it the appropriate MIME-type for #
# your output, and it will change the header accordingly.  You can use it    #
# like this:                                                                 #
#                                                                            #
#   $PAGE->printHeader();                                                    #
#   print "<HTML><BODY>A really simple page.</BODY></HTML>";                 #
#   exit;                                                                    #
#                                                                            #
# That will output a page which says 'A really simple page.' and nothing     #
# else.  You might want to use printHeader() instead of sendPage() if you    #
# are creating such a dynamic web page that you need write all the HTML from #
# within your script, rather than using an HTML file as a template and       #
# filling in variables.
##############################################################################

sub new {
    my $class = shift;
    my $self  = {};
    bless $self, $class;

    # Initialize variable where page content will be stored.
    $PAGE_CONTENT = '';
    # Bool to keep track of whether the header has been sent.
    $HEADER_SENT = 0;
    # Bool to determine whether we display ad.
    $DISPLAY_AD  = 1;

    return $self;
}

sub sendPage {
    my($self,$template_location_or_string_ref,$hash_ref) = @_;
    # Define this important string ref.
    my $page_content_ref = \$PAGE_CONTENT;

    # Branch depending on the type of argument passed.
    if (!ref($template_location_or_string_ref)) {
        # Not passed a ref (to SCALAR). Fill $page_content.
        $self->fillString($page_content_ref,
			  $template_location_or_string_ref);

	# For dev: Tack on the location of the template in a comment for
	# reference.
	if ($ENV{'SERVER_NAME'} =~ /^\w+-dev\.tripod\.com/) {
	    $$page_content_ref .= "\n<!-- template path: $template_location_or_string_ref -->\n";
	}
    } else {
        $page_content_ref = $template_location_or_string_ref;
    }

    # Remove ads if necessary.
    if ($DISPLAY_AD != 1) {
	$$page_content_ref =~
	    s|<!--\s*?AD\s*?-->[\s\S]*?<!--\s*?/AD\s*?-->||ig;
    }

    # Interpolate variables as needed.
    $self->varSubstitution($page_content_ref,$hash_ref);

    # Print the header if needed.
    $self->printHeader() if (!$HEADER_SENT);

    # Print the page content to STDOUT.
    print $$page_content_ref;

    # Record that the header has been sent.
    $HEADER_SENT = 1;
}

sub sendNonCachedPage {
    my $self = shift;
    # HTTP/1.0 caches should not store responses that have already expired
    print "Expires: Thu, 27 Feb 1997 21:42:25 GMT\n";
    
    # HTTP/1.1 headers, in case caches recognize at least one of 'em
    print "Cache-control: no-cache\n";
    print "Cache-control: no-store\n";
    print "Cache-control: private\n";

    $self->sendPage(@_);
}

sub printHeader {
    my($self,$mime_type) = @_;
    if (!defined($mime_type) || $mime_type eq '') {
	print "Content-type: text/html\n\n";
    } else {
	print $mime_type, "\n\n";
    }
    $HEADER_SENT = 1;
}

# Set $$content_ref to the content of the template file passed.
sub fillString {
    my($self,$content_ref,$template_location) = @_;
    my($old_newline);
    $old_newline = $/;
    undef $/;
    open(PAGE,"< $template_location");
    $$content_ref = <PAGE>
        || "Couldn't open $template_location";
    close(PAGE);
    $/ = $old_newline;
}

# Interpolate variables into string, but only if values are defined.
sub varSubstitution {
    my($self,$string_ref,$hash_ref) = @_;
    $$string_ref =~ s|\$(\w+)|returnValueOrKey($1,$hash_ref)|eg;
}

sub returnValueOrKey {
    ($key,$hash_ref) = @_;
    if (defined($$hash_ref{$key})) {
        return $$hash_ref{$key};
    } else {
        return '$' . $key;
    }
}

1;
