You are viewing a plain text version of this content. The canonical link for it is here.
Posted to embperl-cvs@perl.apache.org by ri...@apache.org on 2001/02/07 09:21:30 UTC

cvs commit: embperl/test/html/EmbperlObject/sub/subsub/subsubsub eposubsub2.htm

richter     01/02/07 00:21:28

  Modified:    .        Changes.pod Embperl.pm Embperl.xs EmbperlObject.pm
                        INSTALL.pod MANIFEST TODO epdat.h test.pl
               test/conf httpd.conf.src startup.pl
  Added:       .        IntroEmbperlObject.pod TipsAndTricks.pod
               test/cmp eposubsub2.htm
               test/html/EmbperlObject eposubsub2.htm
               test/html/EmbperlObject/sub eposubsub2.htm
               test/html/EmbperlObject/sub/subsub/subsubsub eposubsub2.htm
  Log:
     - Added new Introduction to EmbperlObject written by
       Neil Gunton. See perldoc IntroEmbperlObject
     - Added new Tips and Tricks pod written by
       Neil Gunton. See perldoc TipsAndTricks. Anybody is invited
       to send me their own Tips and Tricks!
     - Fixed a problem that Embperl are in a wired state after an file upload
       has been interrupted. Spotted by Dirk Lutzebaeck.
     - Fixed a problem set @ISA is not correctly setup in case a file is
       compiled in the same package as the base file of EmbperlObject.
       Spotted by Neil Gunton.
     - Fixed problem with including ../foo.html in EmbperlObject. Spotted
       by Neil Gunton.
     - Added warning if @ISA is not correctly setup/corrupted.
  
  Revision  Changes    Path
  1.152     +14 -0     embperl/Changes.pod
  
  Index: Changes.pod
  ===================================================================
  RCS file: /home/cvs/embperl/Changes.pod,v
  retrieving revision 1.151
  retrieving revision 1.152
  diff -u -r1.151 -r1.152
  --- Changes.pod	2001/01/29 10:43:52	1.151
  +++ Changes.pod	2001/02/07 08:20:38	1.152
  @@ -8,6 +8,11 @@
   
   NOTE: This version is only available via L<"CVS"|CVS/"INTRO">
   
  +   - Added new Introduction to EmbperlObject written by
  +     Neil Gunton. See perldoc IntroEmbperlObject
  +   - Added new Tips and Tricks pod written by
  +     Neil Gunton. See perldoc TipsAndTricks. Anybody is invited
  +     to send me their own Tips and Tricks!
      - Added object and isa parameters to Execute, which allows to get an
        object reference for a certain file and set the Perl inherence
        hierachive. Ideas from Neil Gunton and Angus Lees.
  @@ -18,6 +23,15 @@
        on Windows. Based on a patch from Freddy Vulto.
      - Fixed a problem with the cache key, which could cause that the same
        file is compiled within different packages.
  +   - Fixed a problem that Embperl are in a wired state after an file upload
  +     has been interrupted. Spotted by Dirk Lutzebaeck.
  +   - Fixed a problem set @ISA is not correctly setup in case a file is
  +     compiled in the same package as the base file of EmbperlObject.
  +     Spotted by Neil Gunton.
  +   - Fixed problem with including ../foo.html in EmbperlObject. Spotted
  +     by Neil Gunton.
  +   - Added warning if @ISA is not correctly setup/corrupted.
  +    
   
   =head1 1.3.0 (RELEASE)   4 Dec. 2000
   
  
  
  
  1.140     +52 -35    embperl/Embperl.pm
  
  Index: Embperl.pm
  ===================================================================
  RCS file: /home/cvs/embperl/Embperl.pm,v
  retrieving revision 1.139
  retrieving revision 1.140
  diff -u -r1.139 -r1.140
  --- Embperl.pm	2001/01/29 10:43:52	1.139
  +++ Embperl.pm	2001/02/07 08:20:40	1.140
  @@ -10,7 +10,7 @@
   #   IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   #   WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   #
  -#   $Id: Embperl.pm,v 1.139 2001/01/29 10:43:52 richter Exp $
  +#   $Id: Embperl.pm,v 1.140 2001/02/07 08:20:40 richter Exp $
   #
   ###################################################################################
   
  @@ -557,9 +557,10 @@
   sub CheckFile
   
       {
  -    my ($filename, $req_rec, $AllowZeroFilesize, $allow, $pathref, $debug) = @_ ;
  +    my ($filename, $req_rec, $AllowZeroFilesize, $allow, $pathref, $pathndxref, $debug) = @_ ;
   
       my $path = $$pathref ;
  +    my $pathndx = $$pathndxref ;
   
       if (-d $filename)
           {
  @@ -585,14 +586,16 @@
           if ($filename =~ m{^(\.\./|\.\.\\)+?.*?(/|\\)*?(.*?)$}) 
               {
               $filename = $3 ;
  -            $skip = length ($1) / 3 ;
  +            $skip = length ($1) / 3  ;
               }
  +        my $pathskip = $skip ;
  +        $skip += $pathndx if ($skip) ;
           my @path = split /$pathsplit/o, $path ;
           shift @path while (!$path[0]) ;
           shift @path while ($skip--) ;
           my $fn = '' ;
           print LOG "[$$]Embperl path search Path: " . join (';',@path) . " Filename: $filename\n" if ($debug);
  -        $$pathref = join (';', @path) ;
  +        #$$pathref = join (';', @path) ;
   
           foreach (@path)
               {
  @@ -601,6 +604,7 @@
               print LOG "[$$]Embperl path search Check: $fn\n" if ($debug);
               if (-r $fn && (-s _ || $AllowZeroFilesize))
                   {
  +                $$pathndxref = $pathndx + $pathskip ;
                   if (defined ($allow) && !($fn =~ /$allow/))
                       {
   	            logerror (rcNotAllowed, $fn, $req_rec);
  @@ -609,6 +613,7 @@
                   $_[0] = $fn ;
                   return ok ;
                   }
  +            $pathndx++  ;
               }
   
           -r $filename ;
  @@ -788,7 +793,8 @@
       my $Inputfile    = $$req{'inputfile'} || $$req{'isa'} || $$req{'object'} || '?' ;
       my $Sub          = $$req{'sub'} || '' ;
       my $lastreq      = CurrReq () ;
  -    
  +    my $pathndx      = 0 ;
  +
       if ($lastreq)
           {
           if ($Inputfile eq '*') 
  @@ -803,6 +809,7 @@
               }
           $$req{'path'} ||= $lastreq -> Path  ;
           $$req{'debug'} ||= $lastreq -> Debug  ;
  +        $pathndx = $lastreq -> PathNdx ;
           }
       
       if (defined ($In))
  @@ -815,7 +822,7 @@
           #my ($k, $v) ;
           #while (($k, $v) = each (%$req))
           #    { warn "$k = $v" ; }
  -        if ($rc = CheckFile ($Inputfile, $req_rec, (($$req{options} || 0) & optAllowZeroFilesize), $$req{'allow'}, \$req -> {path}, (($$req{debug} || 0) & dbgObjectSearch))) 
  +        if ($rc = CheckFile ($Inputfile, $req_rec, (($$req{options} || 0) & optAllowZeroFilesize), $$req{'allow'}, \$req -> {path}, \$pathndx, (($$req{debug} || 0) & dbgObjectSearch))) 
               {
   	    FreeConfData ($conf) ;
               return $rc ;
  @@ -835,9 +842,14 @@
       my $r = SetupRequest ($ar, $Inputfile, $mtime, $filesize, ($$req{firstline} || 1), $Outputfile, $conf,
                             &epIOMod_Perl, $In, $Out, $Sub, defined ($import)?scalar(caller ($import > 0?$import - 1:0)):'',$SessionMgnt) ;
       
  -    bless $r, $$req{'bless'} if (exists ($$req{'bless'})) ;
  +    if (exists ($$req{'bless'})) 
  +        {
  +        bless $r, $$req{'bless'} 
  +        warn "\@ISA corrupted HTML::Embperl::Req must be a base class of $$req{'bless'}" if (!$r -> isa ('HTML::Embperl::Req')) ; 
  +        }
   
       $r -> Path ($req->{path}) if ($req->{path}) ;
  +    $r -> PathNdx ($pathndx) ;
   
       my $package = $r -> CurrPackage ;
       $evalpackage = $package ;   
  @@ -869,36 +881,41 @@
   	    require CGI ;
   
   	    my $cgi ;
  -	    $cgi = new CGI  ;
  -	    #eval { $cgi = new CGI } ;
  -	    #$r -> logerror (rcCGIError, $@) if ($@) ;
  -		
  -	    @ffld = $cgi->param;
  +	    #$cgi = new CGI  ;
  +	    eval { $cgi = new CGI } ;
  +	    if ($@ || !$cgi)
  +                {
  +                $r -> logerror (rcCGIError, $@)  ;
  +                $@ = '' ;
  +                }
  +            else
  +                {
  +	        @ffld = $cgi->param;
       
  -	    my $params ;
  -    	    foreach ( @ffld )
  -		{
  -    		# the param_fetch needs CGI.pm 2.43
  -		#$params = $cgi->param_fetch( $_ ) ;
  -    		$params = $cgi->{$_} ;
  -		if ($#$params > 0)
  -		    {
  -		    $fdat{ $_ } = join ("\t", @$params) ;
  -		    }
  -		else
  -		    {
  -		    $fdat{ $_ } = $params -> [0] ;
  -		    }
  -		
  -		##print LOG "[$$]FORM: $_=" . (ref ($fdat{$_})?ref ($fdat{$_}):$fdat{$_}) . "\n" if ($dbgForm) ; 
  -		print LOG "[$$]FORM: $_=$fdat{$_}\n" if ($dbgForm) ; 
  -
  -		if (ref($fdat{$_}) eq 'Fh') 
  +	        my $params ;
  +    	        foreach ( @ffld )
   		    {
  -		    $fdat{"-$_"} = $cgi -> uploadInfo($fdat{$_}) ;
  -		    }
  -		}
  -
  +    		    # the param_fetch needs CGI.pm 2.43
  +		    #$params = $cgi->param_fetch( $_ ) ;
  +    		    $params = $cgi->{$_} ;
  +		    if ($#$params > 0)
  +		        {
  +		        $fdat{ $_ } = join ("\t", @$params) ;
  +		        }
  +		    else
  +		        {
  +		        $fdat{ $_ } = $params -> [0] ;
  +		        }
  +		    
  +		    ##print LOG "[$$]FORM: $_=" . (ref ($fdat{$_})?ref ($fdat{$_}):$fdat{$_}) . "\n" if ($dbgForm) ; 
  +		    print LOG "[$$]FORM: $_=$fdat{$_}\n" if ($dbgForm) ; 
  +
  +		    if (ref($fdat{$_}) eq 'Fh') 
  +		        {
  +		        $fdat{"-$_"} = $cgi -> uploadInfo($fdat{$_}) ;
  +		        }
  +            	    }
  +                }
   	    }
   
   	my $saved_param = undef;
  
  
  
  1.38      +11 -0     embperl/Embperl.xs
  
  Index: Embperl.xs
  ===================================================================
  RCS file: /home/cvs/embperl/Embperl.xs,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -r1.37 -r1.38
  --- Embperl.xs	2000/11/17 05:30:48	1.37
  +++ Embperl.xs	2001/02/07 08:20:42	1.38
  @@ -389,6 +389,17 @@
   OUTPUT:
       RETVAL
   
  +int
  +embperl_PathNdx(r,nNdx=-1)
  +    tReq * r
  +    int    nNdx
  +CODE:
  +    if (nNdx >= 0)
  +        r -> nPathNdx = nNdx ;
  +    RETVAL = r -> nPathNdx ;
  +OUTPUT:
  +    RETVAL
  +
   char *
   embperl_ReqFilename(r)
       tReq * r
  
  
  
  1.41      +2 -4      embperl/EmbperlObject.pm
  
  Index: EmbperlObject.pm
  ===================================================================
  RCS file: /home/cvs/embperl/EmbperlObject.pm,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- EmbperlObject.pm	2001/01/29 10:43:55	1.40
  +++ EmbperlObject.pm	2001/02/07 08:20:43	1.41
  @@ -10,7 +10,7 @@
   #   IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   #   WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   #
  -#   $Id: EmbperlObject.pm,v 1.40 2001/01/29 10:43:55 richter Exp $
  +#   $Id: EmbperlObject.pm,v 1.41 2001/02/07 08:20:43 richter Exp $
   #
   ###################################################################################
   
  @@ -216,7 +216,6 @@
           if (-e $fn)
               {
               $r -> filename ($fn) if ($r) ;
  -            $r -> notes ('EMBPERL_searchpath',  $searchpath) if ($r) ;
               $found = 1 ;
               }
           else
  @@ -245,7 +244,6 @@
               if (-e $fn)
                   {
                   $r -> filename ($fn) if ($r) ;
  -                $r -> notes ('EMBPERL_searchpath',  $searchpath) if ($r) ;
                   $found = 1 ;
                   last ;
                   }
  @@ -296,7 +294,7 @@
                   }
   
               no strict ;
  -            @{"$package\:\:ISA"} = ($basepackage) ;
  +            @{"$package\:\:ISA"} = ($basepackage) if ($package ne $basepackage) ;
               use strict ;
               }
   
  
  
  
  1.16      +6 -0      embperl/INSTALL.pod
  
  Index: INSTALL.pod
  ===================================================================
  RCS file: /home/cvs/embperl/INSTALL.pod,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- INSTALL.pod	2000/12/23 20:13:19	1.15
  +++ INSTALL.pod	2001/02/07 08:20:45	1.16
  @@ -188,11 +188,17 @@
   See L<"perldoc Intro"|"Intro.pod"> for an step by step 
   introduction to Embperl.
   
  +See L<"perldoc IntroEmbperlObject"|"IntroEmbperlObject.pod"> for an step by step 
  +introduction to the OO features of Embperl.
  +
   See L<"perldoc Embperl"|"Embperl.pod"> for complete documentation.
   
   See the L<"eg/"|"Examples.pod"> directory for examples.
   
   See L<"perldoc Faq"|"Faq.pod"> for Frequently Asked Questions.
  +
  +See L<"perldoc TipsAndTricks"|"TipsAndTricks.pod"> for Tips and Tricks 
  +around Embperl.
   
   or you can view it online on http://perl.apache.org/embperl/
   
  
  
  
  1.62      +6 -0      embperl/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /home/cvs/embperl/MANIFEST,v
  retrieving revision 1.61
  retrieving revision 1.62
  diff -u -r1.61 -r1.62
  --- MANIFEST	2001/01/15 20:17:32	1.61
  +++ MANIFEST	2001/02/07 08:20:46	1.62
  @@ -18,6 +18,8 @@
   EmbperlD.pod
   IntroD.pod
   FeaturesD.pod
  +IntroEmbperlObject.pod
  +TipsAndTricks.pod
   typemap
   eg/README
   eg/images/jazzbkgd.gif
  @@ -155,6 +157,9 @@
   test/html/EmbperlObject/epodiv.htm
   test/html/EmbperlObject/sub/subsub/eposubsub.htm
   test/html/EmbperlObject/sub/subsub/subsubsub/eposubsub.htm
  +test/html/EmbperlObject/eposubsub2.htm
  +test/html/EmbperlObject/sub/eposubsub2.htm
  +test/html/EmbperlObject/sub/subsub/subsubsub/eposubsub2.htm
   test/html/EmbperlObject/eposubsub.htm
   test/html/EmbperlObject/sub/epohead.htm
   test/html/EmbperlObject/sub/epopage2.htm
  @@ -258,6 +263,7 @@
   test/cmp/epodiv.htm
   test/cmp/epopage2.htm
   test/cmp/eposubsub.htm
  +test/cmp/eposubsub2.htm
   test/cmp/eposubsub.htm3
   test/cmp/epoobj1.htm
   test/cmp/epoobj2.htm
  
  
  
  1.106     +2 -0      embperl/TODO
  
  Index: TODO
  ===================================================================
  RCS file: /home/cvs/embperl/TODO,v
  retrieving revision 1.105
  retrieving revision 1.106
  diff -u -r1.105 -r1.106
  --- TODO	2001/01/29 10:43:55	1.105
  +++ TODO	2001/02/07 08:20:48	1.106
  @@ -70,6 +70,8 @@
   Test
   ----
   - test FORBIDDEN
  +
  +- test Embperl_debug 0
   
   Bugs
   ----
  
  
  
  1.27      +1 -0      embperl/epdat.h
  
  Index: epdat.h
  ===================================================================
  RCS file: /home/cvs/embperl/epdat.h,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- epdat.h	2000/12/03 13:54:34	1.26
  +++ epdat.h	2001/02/07 08:20:49	1.27
  @@ -351,6 +351,7 @@
       int	    nSessionMgnt ;	/* how to retrieve the session id */
       int	    nInsideSub ;	/* Are we inside of a sub? */
       int	    bExit ;		/* We should exit the page */
  +    int	    nPathNdx ;		/* gives the index in the path where the current file is found */
   #ifdef EP2
       bool    bEP1Compat ;	/* run in Embperl 1.x compatible mode */    
       tPhase  nPhase ;		/* which phase of the request we are in */
  
  
  
  1.92      +4 -0      embperl/test.pl
  
  Index: test.pl
  ===================================================================
  RCS file: /home/cvs/embperl/test.pl,v
  retrieving revision 1.91
  retrieving revision 1.92
  diff -u -r1.91 -r1.92
  --- test.pl	2001/01/29 10:43:57	1.91
  +++ test.pl	2001/02/07 08:20:51	1.92
  @@ -426,6 +426,10 @@
           'cgi'        => 0,
           'cmpext'     => '3',      
           },
  +    'EmbperlObject/sub/subsub/subsubsub/eposubsub2.htm' => { 
  +        'offline'    => 0,
  +        'cgi'        => 0,
  +        },
       'EmbperlObject/sub/eponotfound.htm' => { 
           'offline'    => 0,
           'cgi'        => 0,
  
  
  
  1.1                  embperl/IntroEmbperlObject.pod
  
  Index: IntroEmbperlObject.pod
  ===================================================================
  =pod
  
  
  =head1 Contents
  
  =over 4
  
  =item	Introduction
  
  =item	Getting Started
  
  =item	Hello World
  
  =item	Website-Global Variables
  
  =item	Modular Files
  
  =item	Modular File Inheritance
  
  =item	Subroutines in EmbperlObject
  
  =item	Conclusions
  
  =back
  
  
  =head1 Introduction
  
  This tutorial is intended as a complement to the Embperl
  documentation, not a replacement. We assume a basic familiarity with
  Apache, mod_perl, and Perl, and the Embperl documentation. No prior
  experience with EmbperlObject is assumed. The real purpose here is to
  give a clearer idea of how EmbperlObject can help you to build large
  websites. We give example code which could serve as a starting
  template for your own projects, and hints about best practices which
  have come out of real experience using the toolkit. As always, there
  is more than one way to do it!
  
  Since EmbperlObject is an evolving tool, it is likely that these
  design patterns will evolve over time, and it is recommended that the
  reader check back on the Embperl website for new versions from time to
  time.
  
  =head2 Motivation: Constructing Modular Websites
  
  Embperl is a tool which allows you to embed Perl code in your HTML
  documents. As such, it could by itself handle just about everything
  you need to do with your website. So what is the point of
  EmbperlObject? What does it give us that we don't already get with
  basic Embperl?
  
  As often seems to be the case with Perl, the answer has to do with
  laziness. We would all like the task of building websites to be as
  simple as possible. Anyone who has had to build a non-trivial site
  using pure HTML will have quickly experienced the irritation of having
  to copy-and-paste common code between documents - stuff like
  navigation bars and table formats. We have probably all wished for an
  "include" HTML tag. EmbperlObject goes a long way toward solving this
  problem, without requiring the developer to resort to a lot of
  customized Perl code. 
  
  In a nutshell, EmbperlObject extends Embperl by enabling the
  construction of websites in a modular, or object-oriented, fashion. I
  am using the term "object-oriented" (OO) loosely here in the context
  of inheritance and overloading, but you don't really need to know
  anything about the OO paradigm to benefit from EmbperlObject. As you
  will see from this short tutorial, it is possible to benefit from
  using EmbperlObject with even a minimal knowledge of Perl. With just a
  little instruction, in fact, pure HTML coders could use it to improve
  their website architecture. Having said that, however, EmbperlObject
  also provides for more advanced OO functionality, as we'll see later.
  
  
  =head1 Getting Started
  
  We'll assume here that you've successfully installed the latest
  Apache, mod_perl and Embperl on your system. That should all be
  relatively painless - problems normally occur when mixing older
  versions of one tool with later versions of another. If you can, try
  to download the latest versions of everything.
  
  Having done all that, you might want to get going with configuring a
  website. The first thing you need to do is set up the Apache config
  file, usually called F<httpd.conf>.
  
  =head2 Configuring F<httpd.conf>
  
  The following is an example configuration for a single virtual host to
  use EmbperlObject. There are, as usual, different ways to do this; but
  if you are starting from scratch then it may be useful as a
  template. It works with the later versions of Apache (1.3.6 and
  up). Obviously, substitute your own IP address and domain name. 
  
  	NameVirtualHost 10.1.1.3:80
  
  	<VirtualHost 10.1.1.3:80>
  		ServerName www.mydomain.com
  		ServerAdmin webmaster@mydomain.com
  		DocumentRoot /www/mydomain/com/htdocs
  		DirectoryIndex index.html
  		ErrorLog /www/mydomain/com/logs/error_log
  		TransferLog /www/mydomain/com/logs/access_log
  		PerlSetEnv EMBPERL_ESCMODE 0
  		PerlSetEnv EMBPERL_OPTIONS 16
  		PerlSetEnv EMBPERL_MAILHOST mail.mydomain.com
  		PerlSetEnv EMBPERL_OBJECT_BASE base.html
  		PerlSetEnv EMBPERL_OBJECT_FALLBACK notfound.html
  		PerlSetEnv EMBPERL_DEBUG 0
  	</VirtualHost>
  
  	# Set EmbPerl handler for main directory
  	<Directory "/www/mydomain/com/htdocs/">
  		<FilesMatch ".*\.(html)$">
  			SetHandler  perl-script
  			PerlHandler HTML::EmbperlObject
  			Options     ExecCGI
  		</FilesMatch>
  	</Directory>
  
  Note that you can change the file extension in the FilesMatch
  directive, for example if you like .epl as a file
  extension. Personally, I use .html simply because I can edit files
  using my favorite editor (emacs) and it will automatically load html
  mode. Plus, this may be a minor thing - but using .html rather than a
  special extension such as .epl adds a small amount of security to your
  site since it provides no clue that the website is using Embperl. If
  you're careful about the handling of error messages, then there never
  be any indication of this. These days, the less the script kiddies can
  deduce about you, the better...
  
  So how does all this translate into a real website?
  
  
  =head1 Hello World
  
  The file specified by the EMBPERL_OBJECT_BASE apache directive
  (usually called F<base.html>) is the lynchpin of how EmbperlObject
  operates. Whenever a request comes in for any page on this website,
  Emperl will look for F<base.html> - first in the same directory as the
  request, and if not found there then working up the directory tree to
  the root dir of the website. For example, if a request comes in for
  http://www.yoursite.com/foo/bar/file.html, then Embperl first looks
  for F</foo/bar/base.html>. If it doesn't find F<base.html> there, then
  it looks in F</foo/base.html>. If no luck, then finally
  F</base.html>. (These paths are all relative to the document root for
  the website). What is the point of all this?
  
  In a nutshell, F<base.html> is a template for giving a common
  look-and-feel to your web pages. This file is what is actually used to
  build the response to any request, regardless of the actual filename
  which was asked for. So even if F<file.html> was requested,
  F<base.html> is what is actually executed. F<base.html> is a normal
  file containing valid HTML mixed with Perl code, but with a couple of
  small differences. Here's a simple 'Hello World' example of this
  approach:
  
  F</base.html>
  
  	<HTML>
  	<HEAD>
  		<TITLE>Some title</TITLE>
  	</HEAD>
  	<BODY>
  	Joe's Website
  	<P>
  	[- Execute ('*') -]
  	</BODY>
  	</HTML>
  
  F</hello.html>
  
  	Hello world!
  
  Now, if the file http://www.yoursite.com/hello.html is requested, then
  F<base.html> is what will actually get executed initially. So where
  does the file F<hello.html> get into the picture? Well, the key is the
  '*' parameter in the call to Execute(). '*' is a special filename,
  only used in F<base.html>. It means, literally, "the filename which
  was actually requested".
  
  What you will see if you try this example is something like this:
  
  	Joe's Website
  
  	Hello world!
  
  As you can see here, the text "Joe's Website" is from F<base.html> and
  the "Hello world!" is from F<hello.html>.
  
  This architecture also means that only F<base.html> has to have the
  boilerplate code which every HTML file normally needs to contain -
  namely the <HTML> <BODY>, </HTML> and so on. Since the '*' file is
  simply inserted into the code, all it needs to contain is the actual
  content which is specific to that file. Nothing else is necessary,
  because F<base.html> has all the standard HTML trappings. Of course,
  you'll probably have more interesting content, but you get the point.
  
  
  =head1 Website-Global Variables
  
  Now let's look at a slightly more interesting example. When you create
  Perl variables in Embperl usually, their scope is the current file;
  so, they are effectively "local" to that file. When you come to split
  your website up into modules, however, it quickly becomes apparent
  that it is very useful to have variables which are global to the
  website, i.e. shared between multiple files.
  
  To achieve this, EmbperlObject has special object which is
  automatically passed to every page as it is executed. This object is
  usually referred to as the "Request" object, because we get one of
  these objects created for every document request that the web server
  receives. This object is passed in on the stack, so you can retrieve
  it using the Perl "shift" statement. This object is also automatically
  destroyed after the request, so the Request object cannot be used to
  store data between requests. The idea is that you can store variables
  which are local to the current request, and shared between all
  documents on the current website; plus, as we'll see later, we can
  also use it to call object methods. For example, Let's say you set up
  some variables in F<base.html>, and then use them in F<file.html>:
  
  F</base.html>
  
  	<HTML>
  	<HEAD>
  		<TITLE>Some title</TITLE>
  	</HEAD>
  	[- 
  		$req = shift;
  		$req->{webmaster} = 'John Smith'
  	-]
  	<BODY>
  	[- Execute ('*') -]
  	</BODY>
  	</HTML>
  
  F</file.html>
  
  	[- $req = shift -]
  	Please send all suggestions to [+ $req->{webmaster} +].
  
  You can see that EmbperlObject is allowing us to set up global
  variables in one place, and share them throughout the website. If you
  place F<base.html> in the root document directory, you can have any
  number of other files in this and subdirectories, and they will all
  get these variables whenever they are executed. No matter which file
  is requested, F</base.html> is executed first, and then the requested
  file.
  
  You don't even need to include the requested '*' file, but the usual
  case would be to do so - it would be a little odd to completely ignore
  the requested file!
  
  
  =head1 Modular Files
  
  The previous example is nice, it demonstrates the basic ability to
  have website-wide variables set up in F<base.html> and then
  automatically shared by all other files. Leading on from this, we
  probably want to split up our files, for both maintainability and
  readability. For example, a non-trivial website will probably define
  some website-wide constants, perhaps some global variables, and maybe
  also have some kind of initialization code which has to be executed
  for every page (e.g. setting up a database connection). We could put
  all of this in F<base.html>, but this file would quickly begin to look
  really messy. It would be nice to split this stuff out into other
  files. For example:
  
  F</base.html>
  
     	<HTML>
  	[- Execute ('constants.html')-]
  	[- Execute ('init.html')-]
     	<HEAD>
  		<TITLE>Some title</TITLE>
  	</HEAD>
  	<BODY>
  	[- Execute ('*') -]
  	</BODY>
  	[- Execute ('cleanup.html') -]
  	</HTML>
  
  F</constants.html>
  
  	[-
  		$req = shift;
  		$req->{bgcolor} = "white";
  		$req->{webmaster} = "John Smith";
  		$req->{website_database} = "mydatabase";
  	-]
  
  F</init.html>
  
  	[-
  		$req = shift;
  		# Set up database connection
  		use DBI;
  		use CGI qw(:standard);
  		$dsn = "DBI:mysql:$req->{website_database}";
  		$req->{dbh} = DBI->connect ($dsn);
  	-]
  
  F</cleanup.html>
  
  	[-
  		$req = shift;
  		# Close down database connection
  		$req->{dbh}->disconnect();
  	-]
  
  You can see how this would be useful, since every page on your site
  now has available a database connection, in $req->{dbh}. Also notice
  that we have a F<cleanup.html> file which is always executed at the
  end - this is very useful for cleaning up, shutting down connections
  and so on.
  
  
  =head1 Modular File Inheritance
  
  To recap, we have seen how we can break our site into modules which
  are common across multiple files, because they are automatically
  included by F<base.html>. Inheritance is a way in which we can make
  our websites even more modular.
  
  Although the concept of inheritance is one that stems from the
  object-oriented paradigm, you really don't need to be an OO guru to
  understand it. We will demonstrate the concept through a simple
  example, leading on from the previous one.
  
  Say you wanted different parts of your website to have different
  <TITLE> tags. You could set the title in each page manually, but if
  you had a number of different pages in each section, then this would
  quickly get tiresome. Now we could split off the <HEAD> section into
  its own file, just like F<constants.html> and F<init.html>, right? But
  so far, it looks like we are stuck with a single F<head.html> file for
  the entire website, which doesn't really help much.
  
  The answer lies in subdirectories. This is the key to unlocking
  inheritance, and one of the most powerful features of
  EmbperlObject. You may use subdirectories currently in your website
  design, maybe for purposes of organization and maintenance. But here,
  subdirectories actually enable you to override files from upper
  directories. This is best demonstrated by example (simplified to make
  this specific point clearer - assume F<constants.html>, F<init.html>
  and F<cleanup.html> are the same as in the previous example):
  
  F</base.html>
  
     	<HTML>
  	[- Execute ('constants.html')-]
  	[- Execute ('init.html')-]
     	<HEAD>
  	[- Execute ('head.html')-]
  	</HEAD>
  	<BODY>
  	[- Execute ('*') -]
  	</BODY>
  	[- Execute ('cleanup.html') -]
  	</HTML>
  
  F</head.html>
  
  	<TITLE>Joe's Website</TITLE>
  
  F</contact/head.html>
  
  	<TITLE>Contacting Joe</TITLE>
  
  Assume here that we have an F<index.html> file in each directory that
  does something useful. The main thing to focus on here is
  F<head.html>. You can see that we have one instance of this file in
  the root directory, and one in a subdirectory, namely
  F</contact/head.html>. Here's the neat part: When a page is requested
  from your website, EmbperlObject will search automatically for
  F<base.html> first in the same directory as the requested page. If it
  doesn't find it there, then it tracks back up the directory tree until
  it does find the file. But then, when executing F<base.html>, any
  files which are Executed (such as F<head.html>) are first looked for
  in the B<original directory> of the requested file. Again, if the file
  is not found there, then EmbperlObject tracks back up the directory
  tree.
  
  So what does this mean exactly? Well, if we have a subdirectory, then
  we can if we want just have the usual F<index.html> file and nothing
  else. In that case, all the files included by F<base.html> will be
  found in the root document directory. But if we redefine F<head.html>,
  as in our example, then EmbperlObject will pick up that version of the
  file whenever we are in the /contact/ subdirectory.
  
  That is inheritance in action. In a nutshell, subdirectories inherit
  files such as F<head.html>, F<constants.html> and so on from upper,
  "parent" directories. But if we want, we can redefine any of these
  files in our subdirectories, thus specializing that functionality for
  that part of our website. If we had 20 .html files in /contact/, then
  loading any one of them would automatically get
  F</contact/head.html>.
  
  This is all very cool, but there is one more wrinkle. Let's say we
  want to redefine F<init.html>, because there is some initialization
  which is specific to the /contact/ subdirectory. That's fine, we could
  create F</contact/init.html> and that file would be loaded instead of
  F</init.html> whenever a file is requested from the /contact/
  subdir. But this also means that the initialization code which is in
  F</init.html> would never get executed, right? That's bad, because the
  base version of the file does a lot of useful set up. The answer is
  simple: For cases like this, we just make sure and call the parent
  version of the file at the start. For example:
  
  F</contact/init.html>
  
  	[- Execute ('../init.html') -]
  
  	[-
  		# Do some setup specific to this subdirectory
  	-]
  
  You can see that the very first thing we do here is to Execute the
  parent version of the file (i.e. the one in the immediate parent
  directory). Thus we can ensure the integrity of the basic
  initialization which every page should receive.
  
  EmbperlObject is very smart about this process. Say, for example, we
  have a situation where we have several levels of subdirectory; then,
  say we only redefine F<init.html> in one of the deeper levels, say
  F</sub/sub/sub/init.html>. Now, if this file tries to Execute
  F<../init.html>, there may not be any such file in the immediate
  parent directory - so EmbperlObject automatically tracks back up the
  directories until it finds the base version, F</init.html>. So, for
  any subdirectory level in your website, you only have to redefine
  those files which are specific to this particular area. This results
  in a much cleaner website.
  
  You may break your files up into whatever level of granularity you
  want, depending on your needs. For instance, instead of just
  F<head.html> you might break it down into F<title.html>,
  F<metatags.html> and so on. It's up to you. The more you split it up,
  the more you can specialize in each of the subdirectories. There is a
  balance however, because splitting things up too much results in an
  overly fragmented site that can be harder to maintain. Moderation is
  the key - only split out files if they contain a substantial chunk of
  code, or if you know that you need to redefine them in subdirectories,
  generally speaking.
  
  
  =head1 Subroutines in EmbperlObject
  
  There are two kinds of inheritance in EmbperlObject. The first is the
  one which we described in the previous section, i.e. inheritance of
  modular files via the directory hierarchy. The other kind, closely
  related, is the inheritance of subroutines (both pure Perl and
  Embperl). In this context, subroutines are really object methods, as
  we'll see below. As you are probably already aware, there are two
  kinds of subroutine in Embperl, for example:
  
  	[!
  		sub perl_sub
  		{
  			# Some perl code
  		}
  	!]
  
  	[$ sub embperl_sub $]
  		Some HTML
  	[$ endsub $]
  
  In EmbperlObject, subroutines become object methods; the difference is
  that you always call an object method through an object reference. For
  example, instead of a straight subroutine call like this:
  
  	foo();
  
  We have instead a call through some object:
  
  	$obj->foo();
  
  EmbperlObject allows you to inherit object methods in much the same
  way as files. Because of the way that Perl implements objects and
  methods, there is just a little extra consideration needed. (Note:
  This is not really a good place to introduce Perl's object
  functionality. If you're not comfortable with inheritance, @ISA and
  object methods, then I suggest you take a look at the book
  "Programming Perl" (O'Reilly) or "Object Oriented Perl" by Damien
  Conway (Manning).)
  
  A simple use of methods can be demonstrated using the following
  example:
  
  F</base.html>
  
  	[! sub title {'Joe's Website'} !]
  	[- $req = shift -]
  	<HTML>
  	<HEAD>
  	<TITLE>[+ $req->title() +]</TITLE>
  	</HEAD>
  	</HTML>
  
  F</contact/index.html>
  
  	[! sub title {'Contacting Joe'} !]
  	[- $req = shift -]
  	<HTML>
  		A contact form goes here
  	</HTML>
  
  This is an alternative way of implementing the previous "contact"
  example, which still uses inheritance - but instead of placing the
  <TITLE> tag in a separate file (F<head.html>), we use a method
  (title()). You can see that we define this method in
  F</base.html>, so any page which is requested from the root directory
  will get the title "Joe's Website". This is a pretty good default
  title. Then, in F</foo/index.html> we redefine the title() method
  to return "Contacting Joe". Inheritance insures that when the call to
  title() occurs in F</base.html>, the correct version of the method
  will be executed. Since F</foo/index.html> has its own version of that
  method, it will automatically be called instead of the base
  version. This allows every file to potentially redefine methods
  which were defined in F</base.html>, and it works well. But, as your
  websites get bigger, you will probably want to split off some routines
  into their own files.
  
  EmbperlObject also allows us to create special files which just
  contain inheritable object methods. EmbperlObject can set up @ISA for
  us, so that the Perl object methods will work as expected. To do this,
  we need to access our methods through a specially created object
  rather than directly through the Request object (usually called $r or
  $req). This is best illustrated by the following example, which
  demonstrates the code that needs to be added to F<base.html> and also
  shows how we implement inheritance via a subdirectory. Once again,
  assume that missing files such as F<constants.html> are the same as
  previously.
  
  F</base.html>
  
     	<HTML>
  	[- $subs = Execute ({object => 'subs.html'}); -]
  	[- Execute ('constants.html') -]
  	[- Execute ('init.html') -]
     	<HEAD>
  	[- Execute ('head.html') -]
  	</HEAD>
  	<BODY>
  	[- Execute ('*', $subs) -]
  	</BODY>
  	[- Execute ('cleanup.html') -]
  	</HTML>
  
  F</subs.html>
  
  	[!
  		sub hello
  		{
  			my ($self, $name) = @_;
  			print OUT "Hello, $name";
  		}
  	!]
  
  F</insult/index.html>
  
  	[-
  		$subs = param[0];
  		$subs->hello ("Joe");
  	-]
  
  F</insult/subs.html>
  
  	[! Execute ({isa => '../subs.html'}) !]
  
  	[!
  		sub hello
  		{
  			my ($self, $name) = @_;
  			$self->SUPER::hello ($name);
  			print OUT ", you schmuck";
  		}
  	!]
  
  If we requested the file F</insult/index.html> then we would see
  something like
  
  	Hello, Joe, you schmuck
  
  So what is happening here? First of all, note that we create a $subs
  object in F<base.html>, using a special call to Execute(). We then
  pass this object to files which will need it, via an Execute()
  parameter. This can be seen with the '*' file.
  
  Next, we have two versions of F<subs.html>. The first, F</subs.html>,
  is pretty straightforward. All we need to do is remember that all of
  these subroutines are now object methods, and so take the extra
  parameter ($self). The basic hello() method simply says Hello to the
  name of the person passed in.
  
  Then we have a subdirectory, called /insult/. Here we have another
  instance of F<subs.html>, and we redefine hello(). We call the parent
  version of the function, and then add the insult ("you schmuck"). You
  don't have to call the parent version of methods you define, of
  course, but it's a useful demonstration of the possibilities.
  
  The file F</insult/subs.html> has to have a call to Execute() which
  sets up @ISA. This is the first line. You might ask why EmbperlObject
  doesn't do this automatically; it is mainly for reasons of
  efficiency. Not every file is going to contain methods which need
  to inherit from the parent file, and so simply requiring this one line
  seemed to be a good compromise. It also allows for a bit more
  flexibility, as you can if you want include other arbitrary files into
  the @ISA tree. 
  
  
  =head1 Conclusions
  
  So there you have it - an introduction to the use of EmbperlObject for
  constructing large, modular websites. You will probably use it to
  enable such things as website-wide navigation bars, table layouts and
  whatever else needs to be modularized.
  
  This document is just an introduction, to give a broad flavor of the
  tool. You should refer to the actual documentation for details.
  
  EmbperlObject will inevitably evolve as developers find out what is
  useful and what isn't. We will try to keep this document up-to-date
  with these changes, but also make sure to check the Embperl website
  regularly for the latest changes.
  
  
  =head1 Author
  
  Neil Gunton neil@nilspace.com
  
  
  
  1.1                  embperl/TipsAndTricks.pod
  
  Index: TipsAndTricks.pod
  ===================================================================
  =pod
  
  
  =head1 Contents
  
  =over 4
  
  =item Tips and Tricks
  
  =item Alternative Way To Do Global Variables, using __PACKAGE__
  
  =item Global Variables Via Namespaces
  
  =item Handling Queries in DBI
  
  =item Handling Exits
  
  =item Handling Errors
  
  =item Development and Production Websites
  
  =back
  
  
  =head1 Tips and Tricks
  
  This document follows on from the EmbperlObject introductory
  tutorial. As you can see from that, EmbperlObject enables extremely
  powerful websites to be built using a very intuitive object-oriented
  structure. Now, we'll look at some additional, "unofficial" techniques
  which may also be useful in certain circumstances.
  
  This is a small collection of personal tricks which I have developed
  over the course of months using EmbperlObject in my own websites. I
  hope they are useful, or at least spur you on to develop your own
  frameworks and share these with others.
  
  =head1 Alternative Way To Do Global Variables, using __PACKAGE__
  
  In the process of developing a large website I have found it can be a
  little onerous at times to use the Request object to pass around
  global data. I would like to just create variables like $xxx rather
  than typing $req->{xxx} all the time. It may not seem like much, but
  after a while your code can start looking a lot more complex because
  of all the extra brackets and suchlike. As a typical lazy programmer,
  I looked for a way to simplify this.
  
  The method I am going to describe should be used with caution, because
  it can increase memory useage rather dramatically if you're not
  careful. The way I use it, no extra memory is used, but you do need to
  be aware of the issues.
  
  Basically, you change the way you include files from F</base.html>, so
  that they are included into the same package as F</base.html>:
  
  	[- Execute ({inputfile => '*', package => __PACKAGE__}) -]
  
  You should only do this with HTML files which are included from
  F</base.html>, not with the files such as F<subs.html> - those files
  have to be in their own packages in order for Perl inheritance to
  work. You can't use this technique with any files which are accessed
  via method calls.
  
  So how does this make things better? Well, since all these files now
  share the same package, any variables which are created in one of the
  files is accessible to any of the other files. This means that if you
  create $xxx in F</init.html>, then you can access $xxx in
  F</head.html> or any other file. This effectively gives you global
  variables across all the files which are included from F</base.html>
  into the same package as F</base.html>.
  
  The thing you need to be careful of here is that if one of these files
  is included more than once elsewhere on the website, then it will be
  seperately compiled for that instance - thus taking up more
  memory. This is the big caveat. As a rule, if your files are all just
  included once by F</base.html>, then you should be fine. Note that
  you'll also need to change any calls to parent files, for example:
  
  F</contact/init.html>
  
  	[- Execute ({inputfile => '../init.html', package => __PACKAGE__}) -]
  
  	[-
  		# Do some setup specific to this subdirectory
  	-]
  
  This is ok, since F<../init.html> will still be compiled into the same
  package as the rest of the files included from F</base.html>, and so
  only one version of it will exist in the Embperl cache. Thus memory
  usage is not increased.
  
  I like this technique because it simplifies the look of my code, which
  is important for projects containing complex algorithms. It is not the
  "official" way to implement globals though, and should be used with
  care.
  
  =head1 Global Variables Via Namespaces
  
  The previous section described a way to share variables between
  different files which are included from F</base.html>, by using the
  same package across all the files. However this doesn't help us much
  when dealing with the method files such as F<subs.html>, because
  these files have to have their own packages - so we are back to square
  one.
  
  There is another way to share variables across even different
  packages, and that is by using namespaces. For variables that need to
  be accessible even from F<subs.html>, you could use a namespace which
  is specific to your website. For example, if your website domain is
  mydomain.com, then you could create variables using the form
  
  	$mydomain::xxx = "hello";
  
  As long as you then make sure that you only use this namespace on this
  website (and other websites on the same Apache web server use their
  own namespaces), then you shouldn't get any conflicts. Once again, use
  this with caution, since you introduce the possibility of
  inadvertently sharing variables between completely different
  websites. For example, if you cut and paste some useful code from one
  website to another, you will need to make sure you change the
  namespace of any globals. Otherwise, you could get some very obscure
  bugs, since different requests to the various websites could conflict.
  
  You also need to be careful about variable initialization, since these
  globals will now exist between different requests. So, it's possible
  that if you don't re-initialize a global variable, then it may contain
  some random value from a previous request. This can result in obscure
  bugs. Just be careful to initialize all variables properly and you'll
  be fine.
  
  Finally, note that Embperl will only clean up variables which don't
  have an explicit package (i.e. are in one of the packages
  automatically set up by Embperl). Variables in other namespaces are
  not automatically cleaned up. As a result, you need to pay closer
  attention to cleaning up if you use your own namespaces. The safe way
  to clean up a variable is simply to 'undef' it.
  
  =head1 Handling Queries in DBI
  
  If you are like me, you probably use DBI extensively to enable your
  dynamic websites. I have found the cleanup of queries to be onerous -
  e.g. calling finish() on queries. If you don't do that, then you tend
  to get warnings in your error log about unfinished queries.
  
  What I do these days is use a global hash, called e.g. %domain::query
  (see the previous section for using namespaces to safely implement
  global variables). Then, whenever I create a query, I use this
  variable. For example:
  
  	$domain::query{first_page} = $domain::dbh->prepare (qq{
  		SELECT *
  		FROM pages
  		WHERE page = 1
  		});
  	$domain::query{first_page}->execute();
  	my $first_page = $domain::query{first_page}->fetchrow_hashref();
  
  This little pattern, I find, makes all my queries easier to read and
  keep track of. You give each one a name in the %domain::query hash
  that makes sense. Then, at the end of each request, in the
  F</cleanup.html> file, you can do something like this:
  
  	while (($name, $query) = each (%domain::query))
  	{
  		$query->finish();
  	}
  	$domain::dbh->disconnect();
  
  Once again, this method is not really the "official" way of doing
  things in Embperl. You should use the Request object to pass around
  global variables if you're not comfortable with the risks involved
  with namespaces (e.g. conflicting websites on the same web server).
  
  =head1 Handling Exits
  
  You will often find that you want to terminate a page before the
  end. This doesn't necessarily indicate an error condition; it can be
  just that you've done all you want to do. When you do this, it is good
  to first clean up, otherwise you can get annoying warnings showing up
  in your error logs.
  
  I use the following framework. F</cleanup.html> is Executed from
  F</base.html>, and it is the last thing that is done. It calls the
  cleanup() function in the F</subs.html> file:
  
  F</cleanup.html>
  
  	[-
  		$subs->cleanup ();
  	-]
  
  F</subs.html>
  
  	[!
  		sub cleanup
  		{
  			while (($name, $query) = each (%domain::query))
  			{
  				$query->finish();
  			}
  			$domain::dbh->disconnect();
  		}
  
  		sub clean_exit
  		{
  			cleanup();
  			exit();
  		}
  	!]
  
  Now, whenever I want to exit prematurely, I use a call to
  $subs->clean_exit() rather than just exit(). This makes sure that the
  queries and database connections are shut down nicely.
  
  =head1 Handling Errors
  
  The EMBPERL_OBJECT_FALLBACK directive in F<httpd.conf> allows you to
  set a file which will be loaded in the event that the requested file
  is not found. This file should be relative to the same directory as
  F<base.html>. 
  
  I have found that making a special /errors/ directory is useful,
  because it enables that special subdirectory to define its own
  F<head.html> file, F<init.html> and so on.  So, I then just put this
  in F</notfound.html>:
  
  	[-
  		$http_headers_out{'Location'} = "/errors/";
  		clean_exit();
  	-]
  
  See the previous section, "Handling Exits" for more on clean_exit().
  
  =head1 Development and Production Websites
  
  When I am developing a website, I usually use at least two machines. I
  have a workstation where I do developing and testing, and a separate
  production server, which is accessed by the public. When I am finished
  making changes to the development version of the website, I move it
  over to the production server for testing there. However when I do
  this, I usually don't copy it immediately over the existing production
  version, because there are sometimes issues with Perl modules which
  haven't been installed on the server, or other issues which break the
  code on a different machine. So I use a separate virtual server and
  subdomain (which is easy if you run your own DNS) to test the new
  version. For example if the production version of the server is at
  www.mydomain.com, then I might do testing on the production server
  under test.mydomain.com, or beta. or whatever subdomain you like. This
  means you have to create a new virtual server in the httpd.conf
  file. You also obviously create a new directory for the test server
  (see below for an example).
  
  When you do all this, you end up with a very nice, isolated testing
  environment on the same server as production. Obviously you hopefully
  did all your major testing on your workstation, where you can crash
  the machine and it doesn't matter too much. The production server
  testbed is a last staging area before production, to get rid of any
  lingering glitches or omissions. When you're sure it's all working
  correctly you just copy the files from one directory tree (test) to
  another (production) on the same machine. This test server can also be
  used as a beta of the new production version. Friendly users can be
  given access to the new version, while the old version is still
  running.
  
  One issue that comes up when you do this is that of databases. It is
  very likely that you will be using a special test database rather than
  the live one to test your new version. It would be very unwise to use
  a production database for testing. So your production database might
  be called "mydatabase", and the test one called
  "mydatabase_test". This is fine, but it means that you have to
  remember to change the database name in your code when you copy the
  files over to production. This is very error prone. The solution is to
  set variables like the database name in httpd.conf, by setting an
  environment variable. You just add it to the virtual server section.
  
  Here is a real example of two virtual servers on the same production
  machine, which use two different directories, separate log files and
  different databases. The website is crazyguyonabike.com, which is a
  journal of a bicycle ride I did across America in 1998. I decided to
  expand the site to allow other cyclists to upload their own journals,
  which resulted in substantial changes to the code. I wanted to keep
  the original site up while testing the new version, which I put under
  new.crazyguyonabike.com. Here are the relevant apache settings:
  
  F</etc/apache/httpd.conf>
  
  	# The production server
  	<VirtualHost 10.1.1.2:80>
  		ServerName www.crazyguyonabike.com
  		SSLDisable
  		ServerAdmin neil@nilspace.com
  		DocumentRoot /www/crazyguyonabike/com/htdocs
  		DirectoryIndex index.html
  		ErrorLog /www/crazyguyonabike/com/logs/error_log
  		TransferLog /www/crazyguyonabike/com/logs/access_log
  		ErrorDocument 403 /
  		ErrorDocument 404 /
  		PerlSetEnv WEBSITE_DATABASE crazyguyonabike
  		PerlSetEnv WEBSITE_ROOT /www/crazyguyonabike/com/htdocs
  		PerlSetEnv EMBPERL_DEBUG 0
  		PerlSetEnv EMBPERL_ESCMODE 0
  		PerlSetEnv EMBPERL_OPTIONS 16
  		PerlSetEnv EMBPERL_MAILHOST mail.nilspace.com
  		PerlSetEnv EMBPERL_OBJECT_BASE base.html
  		PerlSetEnv EMBPERL_OBJECT_FALLBACK notfound.html
  	</VirtualHost>
  
  	<VirtualHost 10.1.1.2:80>
  		ServerName crazyguyonabike.com
  		Redirect / http://www.crazyguyonabike.com
  	</VirtualHost>
  
  	# Set EmbPerl handler for main directory
  	<Directory "/www/crazyguyonabike/com/htdocs/">
  		<FilesMatch ".*\.html$">
  			SetHandler  perl-script
  			PerlHandler HTML::EmbperlObject
  			Options     ExecCGI
  		</FilesMatch>
  	</Directory>
  
  	# The test server
  	<VirtualHost 10.1.1.2:80>
  		ServerName new.crazyguyonabike.com
  		SSLDisable
  		ServerAdmin neil@nilspace.com
  		DocumentRoot /www/crazyguyonabike/com/new
  		Alias /pics /www/crazyguyonabike/com/pics
  		DirectoryIndex index.html
  		ErrorLog /www/crazyguyonabike/com/logs/new_error_log
  		TransferLog /www/crazyguyonabike/com/logs/new_access_log
  		ErrorDocument 401 /user/register/
  		ErrorDocument 403 /
  		ErrorDocument 404 /
  		PerlSetEnv WEBSITE_DATABASE crazyguyonabike_new
  		PerlSetEnv WEBSITE_ROOT /www/crazyguyonabike/com/new
  		PerlSetEnv EMBPERL_DEBUG 0
  		PerlSetEnv EMBPERL_ESCMODE 0
  		PerlSetEnv EMBPERL_OPTIONS 16
  		PerlSetEnv EMBPERL_MAILHOST mail.nilspace.com
  		PerlSetEnv EMBPERL_OBJECT_BASE base.html
  		PerlSetEnv EMBPERL_OBJECT_FALLBACK notfound.html
  	</VirtualHost>
  
  	# Set EmbPerl handler for new directory
  	<Directory "/www/crazyguyonabike/com/new/">
  		<FilesMatch ".*\.html$">
  			SetHandler  perl-script
  			PerlHandler HTML::EmbperlObject
  			Options     ExecCGI
  		</FilesMatch>
  	</Directory>
  
  	# Restrict access to test server
  	<Directory /www/crazyguyonabike/com/new>
  		AuthType Basic
  		AuthName CrazyTest
  		Auth_MySQL_DB http_auth
  		Auth_MySQL_Encryption_Types Plaintext
  		require valid-user
  		PerlSetEnv EMBPERL_OPTIONS 16
  		PerlSetEnv EMBPERL_MAILHOST mail.nilspace.com
  	</Directory>
  
  Note that the test and production servers each get their own
  databases, directories and log files.
  
  You can also see that I restrict access to the test server (which is
  generally wise, unless you actually like hackers potentially screwing
  with your head while testing). For basic authentication I use
  mod_auth_mysql, which is available from the MySQL website. It is nice
  because it allows you to authenticate based on a MySQL database.
  
  When you use PerlSetEnv to pass in variables, you access these
  variables in your code as follows:
  
  	$db_name = $ENV{WEBSITE_DATABASE};
  
  If you move those constants which differ between the test and
  production versions of the same code into the httpd.conf file, then
  you can just copy the files over from the test directories to the
  production directory without any alterations. This cuts down on
  editing errors and also documents specific constants in one place.
  
  
  =head1 Author
  
  Neil Gunton neil@nilspace.com
  
  
  
  1.1                  embperl/test/cmp/eposubsub2.htm
  
  Index: eposubsub2.htm
  ===================================================================
   <html>
   <head>
   <title>Example</title>
   </head>
   <body>
    <h1>another head from sub</h1>
  
  --->
  
  eposubsub2 in sub/subsub/subsubsub
  
  ../eposubsub2
  --->
  
  eposubsub2 in sub
  
  ../eposubsub2
  --->
  
  eposubsub2 in /
  
  
  <---
  <---
  <---
   <hr> Footer <hr>
   
   
  
  </body>
   </html>
  
  
  
  
  1.33      +2 -0      embperl/test/conf/httpd.conf.src
  
  Index: httpd.conf.src
  ===================================================================
  RCS file: /home/cvs/embperl/test/conf/httpd.conf.src,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- httpd.conf.src	2001/01/29 10:44:04	1.32
  +++ httpd.conf.src	2001/02/07 08:21:12	1.33
  @@ -46,6 +46,8 @@
   SetEnv EMBPERL_VIRTLOG /embperl/log
   PerlSetEnv EMBPERL_LOG $EPPATH/test/tmp/test.log
   SetEnv EMBPERL_LOG $EPPATH/test/tmp/test.log
  +
  +
   EOD
   
   
  
  
  
  1.11      +1 -0      embperl/test/conf/startup.pl
  
  Index: startup.pl
  ===================================================================
  RCS file: /home/cvs/embperl/test/conf/startup.pl,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- startup.pl	2001/01/29 10:44:05	1.10
  +++ startup.pl	2001/02/07 08:21:14	1.11
  @@ -10,6 +10,7 @@
           }
       } ;
   
  +sub main::trans { return -1 } ;
   
   use Apache ;
   use Apache::Registry ;
  
  
  
  1.1                  embperl/test/html/EmbperlObject/eposubsub2.htm
  
  Index: eposubsub2.htm
  ===================================================================
  --->
  
  eposubsub2 in /
  
  
  <---
  
  
  1.1                  embperl/test/html/EmbperlObject/sub/eposubsub2.htm
  
  Index: eposubsub2.htm
  ===================================================================
  --->
  
  eposubsub2 in sub
  
  ../eposubsub2
  [- Execute ('../eposubsub2.htm') ; -]
  
  <---
  
  
  1.1                  embperl/test/html/EmbperlObject/sub/subsub/subsubsub/eposubsub2.htm
  
  Index: eposubsub2.htm
  ===================================================================
  --->
  
  eposubsub2 in sub/subsub/subsubsub
  
  ../eposubsub2
  [- Execute ('../eposubsub2.htm') ; -]
  
  <---