                    DYNAMIC WEBSITE GENERATOR
----------------------------------------------------------------------

by Darren Duncan <perl@DarrenDuncan.net>

CONTENTS

* Preface
* Description
* Keeping Up To Date
* Requirements
* Installation
* Module List
* How to Use the Modules
* Features
* Support
* To Do
* Program Example
* Author

PREFACE

This distribution features 11 Perl 5 modules that all belong in the temporary 
CGI::WPM::* namespace.  These modules are not officially registered, as they are 
in a state of change.  As such they are subject to be renamed, some could be 
split up and others combined.  However, they are perfectly usable as is.

All of my modules have complete POD inside of them, so please refer to that for a
description of the modules themselves.  Look at CGI::WPM::Globals and 
CGI::WPM::Base in particular because they are the core of the system.

This Read Me document concerns itself mainly with installation and support
issues, and also includes a "To Do" list and other overview documentation.

DESCRIPTION

CGI-WebsiteGenerator is a collection of Perl 5 modules that were developed
originally to implement (generate/compile) an unlimited number of unrelated
dynamic web-sites at once.  The web sites can contain any combination of static
pages or self-referencing forms, perform redirection and track their usage. 
However, each type of component can be used independantly as well, so you can
have standalone guest books or survey forms or usage counters.

The intent here was to maximize code reuse such that each instance of a web site
needs very little of its own Perl code to differentiate it from others.  As such,
each "site" consists mostly of a set of hierarchically organized data files, such
as the htmlized text for each page, settings/configuration files that say things
like what questions are asked in forms such as guestbooks, and log files for the
likes of guest books or usage count data.  Modules are designed such that their
behaviour is customized by giving them different data or "preferences", rather
than by changing the values of hardcoded constants.  Everything is designed with
an extensible architecture so third parties can add features to it.  One ultimate
goal is that website owners can update their sites using their web browsers over
a user-friendly interface.

The modules are compatible with the mod_perl environment in addition to the CGI
environment.  This means that I have tested all of the modules in a production
mod_perl environment (my web sites) and found that they function properly within
the demands that I place on them.  Prior to release 0.32 my only test environment
was CGI.  More to the point, you should be able to write programs to these 
modules and run them unchanged on either a CGI or mod_perl system, as my modules 
will worry about the differences.  Of course, you still have to meet the 
"good programming style" that mod_perl requires on your own...

To see living examples of these modules in use, check out my web sites at
"http://www.DarrenDuncan.net" and "http://www.chronology.net".

KEEPING UP TO DATE

My module set is constantly under development.  You should be able to find the
newest versions at my website, "http://www.DarrenDuncan.net", on the page called
"Perl Libraries I Made" (name subject to change).  They can also be found on CPAN
under the author name of "DUNCAND".  

I am inclined to update the copies on my web site more often, but those
intermediate versions are more likely to have been tested less, and the modules
may be updated day by day without increasing the version numbers.  However, the
copies on CPAN are guaranteed to have unique version numbers when the module has
changed.

REQUIREMENTS

All of my modules require Perl 5.004 or newer, even though only some of them need
it, in the interest of consistency.  That said, Perl 5.004 is already 3 years 
old, is available as a binary on practically every OS that supports Perl at all, 
and is a very solid release, so I see no reason to support anything older.

Modules in this distribution require modules in these following distributions:

HTML-EasyTags-1.03.tar.gz
	- by Darren Duncan (DUNCAND)
	- HTML::EasyTags 1.03 is required by:
		- CGI::WPM::Globals (when assembling a final HTML page only)
		- Anything that uses Globals except when redirection headers and usage

MultiValuedHash-1.06.tar.gz
	- by Darren Duncan (DUNCAND)
	- CGI::MultiValuedHash 1.06 is required by:
		- CGI::WPM::Globals (parsing user input)
		- CGI::WPM::MailForm (for serializing file data)
		- CGI::WPM::GuestBook (for serializing file data)
		- Anything that uses Globals
		- Anything that uses FormTemplate

HTML-FormTemplate-1.05.tar.gz
	- by Darren Duncan (DUNCAND)
	- HTML::FormTemplate 1.05 is required by:
		- CGI::WPM::MailForm (for making input forms and form reports)
		- CGI::WPM::GuestBook (for making input forms and form reports)

libnet-1.0703.tar.gz (older versions may work):
	- by Graham Barr (GBARR)
	- Net::SMTP 2.15 is required by:
		- CGI::WPM::MailForm (when sending e-mails of form data)
		- CGI::WPM::GuestBook (when sending e-mails of form data)
		- CGI::WPM::Usage (when sending e-mails of usage data)

libwww-perl-5.48.tar.gz (older versions may work):
	- by Gisle Aas (GAAS)
	- HTTP::Headers 1.37 is required by:
		- CGI::WPM::Globals (when outputting http headers to the user)

mod_perl-1.24_01.tar.gz (older versions may work):
	- Apache 1.27 is required by:
		- CGI::WPM::Globals (when running under mod_perl)

INSTALLATION

To install this module, cd to the directory that contains all of the extracted 
distribution files, including this ReadMe file, and type the following:

	perl Makefile.PL
	make
	make test
	make install

The last step probably won't work if you are not the administrator of your 
machine; in that case you either need to get your administrator to install this 
for you, or put it in a your own local directory instead.

If you are on a Mac system and/or you are otherwise having problems with the 
Makefile, you can still install this module the old fashioned way, by copying.

All of the ".pm" files in this distribution go inside the temporary folder "WPM",
which is inside "CGI", which is in the "lib" folder that came with your Perl 5
distribution.

Or alternately, put it anywhere you want, but you will need to have that 
location added to your include path by your main program using something like 
this:

	use lib '/users/me/www_files/lib';

Then you would want to run the included test program to make sure the module is 
installed correctly.  Call it with:

	perl test.pl

Any existing POD is embedded in the module itself.  The Makefile probably 
extracted it for you in the usual manner, or you can run a POD extractor on it 
yourself to the same effect.  You can also find an HTMLized copy of the POD on 
CPAN and other public source archives; I link to one copy of it on my web site.

MODULE LIST

Here is a quick list of all the modules in the distribution, and what each is
for.

CGI::WPM::FileVirtualPath - Portable abstraction of a file/dir/url path.

CGI::WPM::CountFile - Perl module that interfaces to a tab-delimited text file
for storing date-bounded counts of occurances for multiple events, such as web
page views.

CGI::WPM::Globals - Perl module that is used by all subclasses of CGI::WPM::Base
for managing global program settings, file system and web site hierarchy
contexts, providing environment details, gathering and managing user input,
collecting and sending user output.

CGI::WPM::Base - Perl module that defines the API for subclasses, which are
miniature applications called "web page makers", and provides them with a
hierarchical environment that handles details for obtaining program settings,
resolving file system or web site contexts, obtaining user input, and sending new
web pages to the user.

CGI::WPM::MultiPage - Perl module that is a subclass of CGI::WPM::Base and
resolves navigation for one level in the web site page hierarchy from a parent
node to its children, encapsulates and returns its childrens' returned web page
components, and can make a navigation bar to child pages.

CGI::WPM::Static - Perl module that is a subclass of CGI::WPM::Base and displays
a static HTML page.

CGI::WPM::MailForm - Perl module that is a subclass of CGI::WPM::Base and
implements an e-mail submission form with unlimited questions.

CGI::WPM::GuestBook - Perl module that is a subclass of CGI::WPM::Base and
implements a complete guest book with unlimited questions that also e-mails 
submissions to the website owner.

CGI::WPM::SegTextDoc - Perl module that is a subclass of CGI::WPM::Base and
displays a static text page, which can be in multiple segments.

CGI::WPM::Redirect - Perl module that is a subclass of CGI::WPM::Base and issues 
an HTTP redirection header.

CGI::WPM::Usage - Perl module that is a subclass of CGI::WPM::Base and tracks
site usage details, as well as e-mail backups of usage counts to the site owner.

HOW TO USE THE MODULES

First of all, it is always a good idea to skim through the POD for any module in
order to learn how to use it.  However, the POD for all the CGI::WPM::* modules
is incomplete right now.  What they do have is Name, Synopsis, and Dependencies, 
as well as a list of their methods and a list of the "preferences" they handle.  
What they lack is Descriptions, Method and Preference descriptions.  These will
be added when I have the time.  Second of all, try looking at the source code 
for the modules when in doubt.  At some point I will include a demo site with 
this distribution, but for now the Synopsis code "should" run.

FEATURES

When all of the modules in this set are used together, these are some of the
features that programs using them can have:

* Fully compliant with the HTML 4.0 standard and Cascading Style Sheets.

* Single or multiple pages in each site, which can be organized hierarchically. 
At each hierarchy level, a naviagation bar can be automatically provided or left
out.

* Display static pages read from an ordinary HTML document; the source can be a
complete HTML document or only that which would go between the 'body' tags.

* Provide html forms for sending private e-mails to the site owner, with a
visitor-defined option for the sender getting their own copy.  The user input is
automatically error-checked for completeness and shows the visitor what they did
wrong if not.  The mail is sent using SMTP directly, so it works on systems that
don't have 'sendmail'.  The number and field type of questions is unlimited, and 
the input validity checking is customizable.

* Provide guest books with all the features of private mail forms and more.  
Guest book entries are displayed with the sender's name and time of submission, 
but their e-mail address is hidden.

* Display plain text documents with their formatting intact (using 'pre' tags)
along with relevant details like title, author, version and dates created or
modified.  Long documents can optionally be segmented and displayed as a series
of parts, which can be navigated with an automatically provided navigation bar.

* Automatically redirect visitors to an external url from an internal one.

* Usage of the site can be counted, and for each usage event are the count of
total occurances, count of today's occurances, date of first occurance, and date
of last occurance.  Usage details that can be counted include: which site pages
were viewed, which external urls we redirect visitors to, which external urls
have a link to us (that were used), and miscellaneous environment details like
GET vs POST vs HEAD requests.  The details are counted independently of each
other.  Usage information can be compiled and e-mailed to the owner once per day
for backup/report purposes.  Referring urls are smartly subgrouped such that
search engines and normal web sites appear separately, and also the search
keywords are in their own group so it is easy to see at a glance what kinds of
searches led visitors to you.

* Search and replace of content at site visitation time so that repeating and/or
complicated data in static source files can be substituted by other static or
dynamic content which changes over time, such as a hyperlink to e-mail the owner
(addresses change), or directory url holding graphics.

* Generated sites are usable on all visitor computing platforms, no matter what
web browsers they have, even if text-only.

* The site can be seamlessly moved from one web or physical address or computer
platform to another, and nothing will break. I have tested it on UNIX, Linux,
Windows, Macintosh successfully. All platform-specific details are confined to a
single site-settings file, which is quoted above.  Most site details are in other
files, which are platform agnostic.  The site can be invoked from a command
prompt for testing if desired.

* The site can be invoked using an optional query parameter that will turn
debugging on.  The site-program will then know that it is the owner viewing the
site, and can do some things differently in accordance. Currently the only
difference is that a separate set of usage logs are kept, so normal hit counters
aren't racked up when testing something.

* The site's support files can all be stored outside the 'public_html' directory,
so attempts to view them directly will fail (no corresponding web url).  Only the
main shell (or link to it) must be in the 'public_html'.

* Hooks are provided so that future versions of this program will let the site
owner edit the site's content using its own web forms.  That is, remote
administration. Currently, the only way to edit a site's content is to use
ftp/telnet to directly change the site support files. For security purposes,
admin_mode can only be invoked by calling a separate module method, which would
likely be in a separate shell/main program.

* The progam modules are designed in an elegant and extensible format, so
additional "plug-in" modules can be made to provide additonal functionality, such
as a threaded discussion board, or database-access pages, without changing the
other program code.  In the future, it should be easy to add features for content
searching and reporting, internal site spidering (more efficient), and more.

* The modules have extensive error checking and graceful exit routines built-in
so that nothing the site visitor does should make the program crash (although the
Perl interpreter itself or the web server is a different story).  If the program
did crash, then the visitor would get a nondescript "server error" message
without any idea why it happened.  Likewise, many checks are in place to account
for problems introduced by the site programmer themselves, such as improperly
made settings, nonexistant files, or non-compiling plug-in modules.  For better
or worse, the program currently gives details on exactly what went wrong, so that
the owner who is testing it has an easy time fixing it.

* The modules are compatible with the mod_perl environment in addition to the CGI
environment.  This means that I have tested all of the modules in a production
mod_perl environment (my web sites) and found that they function properly within
the demands that I place on them.

SUPPORT

Currently I don't have any support arranged with other people, lists, newsgroups,
or otherwise.  Feel free to ask me if you can't figure things out on your own, or
another person whom you know has used this.  I may start a mailing list for 
support issues later, so that users of my modules can help each other with them.

TO DO

	* Break the distribution up into several different ones, separating the 
	generic functionality from the proprietary.  To date, 5 generic modules have 
	already been split off into their own 4 distributions: Class-ParamParser, 
	HTML-EasyTags, MultiValuedHash, HTML-FormTemplate.  Others will follow...

PROGRAM EXAMPLE

Note that this example only uses some of the lower level modules, and also uses 
the HTML-FormTemplate distribution.  See the POD for CGI::WPM::Globals and 
CGI::WPM::Base for examples of the use of my high level modules.

WARNING: as of release 0.35, the SequentialFile module ceased to exist, so the 
following is for historical purposes only.  All of the core functionality was 
transferred to CGI::MultiValuedHash, so you should look there.  Anything else 
that was needed by MailForm or GuestBook has been absorbed into them.  
As of release 0.36, the PageMaker and WebUserIO modules also ceased to exist.  
These are absorbed into Globals so you can use it like you used both of them.

	use HTML::FormTemplate;
	use CGI::WPM::PageMaker;
	use CGI::WPM::SequentialFile;
	use CGI::WPM::WebUserIO;
	
	my @questions = (
		{
			visible_title => "What's your name?",
			type => 'textfield',
			name => 'name',
			is_required => 1,
			error_message => 'You must enter your name.',
			exclude_in_echo => 1,
		}, {
			visible_title => "Your E-mail",
			type => 'textfield',
			name => 'email',
			size => 30,
			is_required => 1,
			validation_rule => '\S\@\S',
			help_message => 'E-mails are in the form "user@domain".',
			error_message => 'You must enter your e-mail.',
		}, {
			visible_title => "What's the combination?",
			type => 'checkbox_group',
			name => 'words',
			'values' => ['eenie', 'meenie', 'minie', 'moe'],
			default => ['eenie', 'minie'],
		}, {
			visible_title => "What's your favorite colour?",
			type => 'popup_menu',
			name => 'color',
			'values' => ['red', 'green', 'blue', 'chartreuse'],
		}, {
			type => 'submit', 
		},
	);
	
	my $webpage = CGI::WPM::PageMaker->new();
	my $query = CGI::WPM::WebUserIO->new();
	my $message_file = CGI::WPM::SequentialFile->new( "GB_Messages.txt", 1 );
	my $form = HTML::FormTemplate->new();
	
	$form->form_submit_url( $query->self_url() );
	$form->field_definitions( \@questions );
	$form->user_input( $query->user_input() );
	
	if( $form->new_form() ) {  # if we're called first time
		$webpage->title( 'Please sign the guest book' );
		$webpage->body_content(
			$form->h1( $webpage->title() ),
			$form->make_html_input_form( 1 )
		);

	} elsif( $form->validate_form_input() ) {  #if there were errors
		$webpage->title( 'Please fix your mistakes' );
		$webpage->body_content(
			$form->h1( $webpage->title() ),
			$form->make_html_input_form( 1 )
		);

	} else {  # submitted answers are fine
		$webpage->title( 'Here is what you signed with' );
		$webpage->body_content(
			$form->h1( $webpage->title() ),
			$form->p( 'From: '.$query->user_input_param( 'name' ) ),
			$form->make_html_input_echo( 1 )
		);
	}
	
	$message_file->append_new_records( $query->user_input() ) or 
		$webpage->body_append( '<P>Unfortunately, there was an error in saving'.
		' your message to the guest book: '.$message_file->is_error()."</P>\n" );
	
	$webpage->body_append( 
		$form->hr(),
		$form->h1( 'Existing Messages' )
	);
	
	my @message_list = $message_file->fetch_all_records( 1 );
	
	if( my $err_msg = $message_file->is_error() ) {
		$webpage->body_append( '<P>Unfortunately, there was an error reading'.
		' the messages from the guest book: '.$err_msg."</P>\n" );

	} else {  # show the existing messages
		my @message_html = ();
		foreach my $message (reverse @message_list) {
			$form->user_input( $message );
			my $name = $message->fetch_value( 'name' );
			push( @message_html, "<H3>From $name:</H3>" );
			push( @message_html, 
				$form->make_html_input_echo( 1, 1, '(no answer)' ) );
		}
		$weboage->body_append( \@message_html );
	}
	
	$query->send_to_user( undef, $webpage->content_as_string() );

AUTHOR

Copyright (c) 1999-2001, Darren R. Duncan. All rights reserved. These modules are
free software; you can redistribute them and/or modify them under the same terms
as Perl itself.  However, I do request that their copyright information remains
attached to the files.  If you modify this module and redistribute a changed
version then please attach a note listing the modifications.

I am always interested in knowing how my work helps others, so if you put this
module to use in any of your own code then please send me the URL.  Also, if you
make modifications to the module because it doesn't work the way you need, please
send me a copy so that I can roll desirable changes into the main release.

Address comments, suggestions, and bug reports to perl@DarrenDuncan.net.

Share and Enjoy!

