Liz::Perl - Elizabeth Mattijsen's Perl Extensions for HTML


 use Liz::Perl;


For the moment, a lot of examples are available at ).


Provide HTML extensions for generating HTML and PHP (2.x) files as well as for dynamically generating HTML under mod_perl.

The idea behind Liz::Perl is basically allowing Perl code to be embedded in standard HTML. Whenever you need something dynamic, you would insert a <PERL> tag, write your Perl statements, finish with </PERL> and continue writing HTML. This is similar to what PHP does, with one big exception: variables can be referenced inside the HTML just like ``The score is <B>$score</B> points''.

Activating Liz::Perl

There are basically two ways in which Liz::Perl can be used:

 1 to create static HTML-files from a database.
   This reduces the load on the server and the database engine.
   Pages can either be plain HTML or HTML enhanced with PHP.

 2 to create interactive pages with Perl.
   In this capacity it is an alternative to writing true Perl scripts
   or to PHP with more capabilities.  Using Liz::Perl as a ModPerl
   handler really makes interactive pages fly.

Static HTML-files

Static HTML-files are created with the Execute method that was preceded by a File method. Basically, you set up a loop in which the necessary global variables are set, then indicate which global variables should be the same in the Safe sandbox and then use the method Execute to create the HTML-file with the associated variables. For example, suppose the file ``template.htm'' contains:

 <TITLE>Page $page</TITLE>
 This is page $page.

And a script called ``generate'' contains:


 use Liz::Perl;
 $lp = new Liz::Perl( 'template.htm' );
 $lp->Same( qw($page) );

 foreach $page ( 1..10 ) {
   $lp->File( "$page.htm" );

Then executing this script would create 10 HTML-files, with the following contents:

 <TITLE>Page 1</TITLE>
 This is page 1.

 <TITLE>Page 2</TITLE>
 This is page 2.

 etc. etc.

Interactive scripts (cgi-bin style)

The other manner with which you can use Liz::Perl is for interactive applications. In this way it is an alternative to writing a script completely in Perl, or as an alternative to PHP. For example a script may contain the following:

 use Liz::Perl;
 <TITLE>Your last name</TITLE>
 <IF $name>
  Your last name is "$lastname".
 Please enter your last name: <TEXT lastname> <SUBMIT Send>

This would ask you for your last name and then display it. Note that from a perspective of use of CPU resources, this is the worst way of using Liz::Perl, because both Liz::Perl and the script need to be processed each time a request is made.

Interactive scripts (ModPerl style)

Using Liz::Perl with ModPerl is making things really easy. Suppose you would like to have all files with the extension .lp be processed by Liz::Perl. The following configuration does that:

 <Files *.lp>
 SetHandler     perl-script
 PerlHandler    Liz::Perl

A file with the extension .lp containing:

 <TITLE>Your last name</TITLE>
 <IF $name>
  Your last name is "$lastname".
 Please enter your last name: <TEXT lastname> <SUBMIT Send>

would then provide the same functionality as the example with the cgi-bin style. But it would be up to 20 times faster because all the necessary modules have been compiled and are in memory already.

Virtual File System

One step further when using Liz::Perl together with ModPerl, is through the use of default page handlers. This causes a generic Liz::Perl script to be called for each page that is requested. This script then in turn can decide whether it is a valid page or not. And if it is a valid page, whether it will be cached for future requests.

This combines the advantages of pre-generated pages (quick reply to browser's requests because most of the processing has already been done) with the flexibility of generating pages on the fly (no worries about needing to generate unneeded pages or pages being out of sync with the database version). To the browser, a page such as /12345.htm would appear completely static, while the page is generated on the fly from the database content the first time a browser requests that page.


If an interactive Liz::Perl script is called, all the variables and values are stored as global variables in the namespace of the script. So, if you have a <INPUT NAME=text> in a FORM, then the characters typed by the user in that field, will be available in the script as the variable $text. There are two special cases:

A HREF=page?value

If the script is called with a GET action (usually by a link in the form <A HREF=script?value>), then the value will be available in the variable $query.

BUTTON name src (INPUT TYPE=image NAME=name SRC=src)

If the script is called by clicking on an image (button), then the variable $action will be set to the name of the image (button) that was clicked. The position at which the image was clicked, is also available in the variable $name_x and $name_y.

No difference between GET and POST

Liz::Perl does not differentiate between values obtained from a GET or a POST action. If you want to make sure that the values that you have received are the result of a POST operation, then you should check $ENV{'REQUEST_METHOD'} and see if it has the value you expect ('GET' or 'POST').

Access to raw input data

The standard variable $GETPOSTDATA contains a reference to a scalar that contains the raw data as entered by the browser to the script. It can be used for debugging purposes, but can also be saved in a database to be able to replicate a situation later. Any values saved can later be activated again by a call to Liz::GetPostData().


A number of standard functions are always available in a Liz::Perl object during execution. They are:

Redirect( $url )

Redirect the user to a different URL. Only makes sense when being used interactively, either in cgi-bin or modperl mode. Any code after a call to this routine, will not be executed. Also accessible with the HTML code REDIRECT location.

NoChange( )

Indicate to the browser that there is no new content and that the current page should not be changed. Only makes senss in modperl interactive mode. Any code after a call to this routine, will not be executed. This is also accessible with the HTML code <NOCHANGE>.

FrozenContent( $lastchanged )

Mark the output of the document as essentially frozen since the date indicated. It currently only makes sense in a ModPerl environment. It allows the browser to re-display the document from its internal cache if it has not been modified.

This functions performs two functions internally:

 1 a Last-Modified header will also be sent to the browser.  This will
   enable the browser to perform a so-called "If-Modified-Since" GET
   the next time the document is requested and the browser still has it
   in its internal cache.

 2 if the document is requested with an "If-Modified-Since" header, then
   the specified date will be matched with the last changed date specified.
   If the last changed date is the same or older than the time that the
   browser specified in the header, all processing will stop immediately
   and a 304 Status (Not Modified) will be sent to the browser, causing it
   to re-display the document from the cache.

The last changed information can be specified as either a Unix time (number of seconds since Jan. 1, 1970) or as a SQL timestamp (YYYYMMDDHHMMSS). Negative values indicate a Unix time relative to now (e.g. -3600 indicating one hour ago). The last modified time of the document itself will in any case be used if it is later than the last changed time specified.

This function is also accesible with the HTML code <FROZENCONTENT>. In that case the last modified date of the document itself will always be used.

The last modified time that was actually used, is returned. This allows pages to indicate at what time the page is ``locked'' in time.

AccessDenied( $reason )

Deny access to the Liz::Perl code. Only makes sense if Liz::Perl::Authenticate is used as the authentication handler for the page. A reason for denying access can be given also: this wil be logged in the server's error log. Any code after a call to this routine, will not be executed. Only makes sense when executed in an interactive ModPerl environment at the moment.

Please note that the environment variables $ENV{'REMOTE_USER'} and $ENV{'REMOTE_USER_PASSWORD'} can be used to check whether a user should be granted access or not.

Header( 'Header-Type: contents' )

Specify a generic HTTP-header for your own use. This can e.g. be used to generate special effects with special browsers.

ContentType( $MIMEtype,$filename )

Specify the content-type (MIME-type) of the data sent to the browser, and optionally as which file it should be known when it arrives. Only makes sense in cgi-bin or modperl interactive mode. Only needed if the content-type needs to be something other than 'text/html' or a filename different from the document, needs to be specified.

The MIMEtype defaults to 'application/octet-stream' if not specified. No Content-Disposition: header is sent to the browser if no filename is specified.

ContentLength( $length )

Specify the number of bytes of data that will be sent to the browser. Only makes sense in an interactive environment and only if the actual number of bytes is known beforehand. If the content length is specified, a user will get a % indication when downloading large files, which can be useful.


Returns true if the browser of the user has broken the connection with the server (this usually happens if the user has clicked in Stop). Can be used to stop the running if large numbers of calculations need to be done and the user has left before the calculation is complete. Only works in a ModPerl interactive mode.

AsIs( $filename )

Send the specified file directly to the browser without loading it into Perl variables when in ModPerl interactive mode. This can be a great space/cpu saver when sending large files in a secure or server push environment. In all other modes, it simply inserts the contents of the specified file, which does take up memory.


Flush any output that was saved since the last call to Flush() (or the beginning of the document, or <FLUSH> pseudo-HTML code) to the browser. Only makes sense in a ModPerl environment.


Stop immediately with execution of the document. Performs the same function as the <STOP> HTML code.


Make sure the current document is not cached. Usually used in default page handlers only. Performs the same function as the <UNCACHE> HTML code.

Warn( $message )

Send a warning message to the HTML-stream of the document. Basically the same as Print( $message ) but will not start the data part of the HTML-stream. Mainly intended to be used by external modules.

GET( $url )

Obtain the contents of a page somewhere on the Internet, as specified by its URL. From the module.

HTML( $filename )

Execute the indicate file as Liz::Perl file and return or print the result. This is not the same as the <INCLUDE ...> HTML code: <INCLUDE ...> works during the compilation of the document and can therefore not accept a variable of the filename to include. HTML on the other hand, does its works during execution and does allow a variable filename or even a HTML-stream (e.g. a processed template). If this function is called in a void context, the result of the execution is printed.

LastModified( $filename1,$filename2... )

Return the last modified date of one or more files. Only the latest date/time will be returned. From the module. Especially handy in conjunction with FrozenContents( $lastchanged ).

Contents( $filename )

Obtain the contents from a file or the output of the execution of a program into a variable. From the module. The opposite of the WriteContents function.

WriteContents( $filename,$contents )

Write the contents of a variable into a file. From the module. The opposite of the Contents function.

Hex2RGB( $hexcode )

Convert a hexadecimal colour code into a three-element integer array. Performs the function opposite to RGB2Hex. Especially handy when using the module. From the module.

RGB2Hex( $red,$green,$blue )

Convert a three-element integer array into a hexadecimal colour code. Performs the function opposite to Hex2RGB. Especially handy when using the module. From the module.

URLEncode( $string )

Encode a string so that it can be used in a URL specification. From the module.

HTMLEncode( $string )

Encode a string so that extende ASCII characters are replaced by HTML entities. From the module.

Scalars2Hash( $namespace,$hash,qw($var1 $var2 $var3) )

Convert a number of variables and their values into a reference to a hash table. Creates a hash table if none given. From the module. The opposite of Hash2Scalars.

Hash2Scalars( \%hash )

Convert a reference to a hash table into variables of the callers or any other namespace. From the module. The opposite of Scalars2Hash.

Benchmark( $string )

Print (or return) the current usage of the CPU. Mainly intended for debugging purposes only. Can also be access from with the HTML code <BENCHMARK>.

Die( $string )

Special function for use within the ModPerl environment. Lets the Apache process that is handling the current request die after the request is completed. This is particularly intended for cases where it is known beforehand that an action (e.g. the generation of HTML-files) will cause the Apache child to use a large amount of unshared memory. For the general performance of the server, it is then important to return this memory for general use as soon as possible. If a string is specified, it is printed to the error log. Can also be accessed from with the HTML code <DIE>.

Otherwise the action is identical to the Stop() function.


There are two ways in which Liz::Perl code can be documented:

# this is a comment

Any line that starts with a ``#'' is considered to be a comment. This applies to both HTML and Perl sections. For example:

 # This is a comment
 <H1>This is HTML</H1>

 # This is another comment

 $variable = 1;

Please note that only lines that start with an ``#'' are considered to be comments. In Perl sections it is in principle also possible to place an ``#'' anywhere in the line, but for reasons of source code clarity, this is advised against.

Also note that lines that start with ``#'' are removed last from the Perl source code. This implies that any line that starts with a ``#'' but that has an <INCLUDE ...> in it, will in fact only comment out the first line of the included file.

&lt;*&gt;This is a comment&lt;/*&gt;

Any code that exists between <*> and </*> is ignored. Note that the code will only be ignored if a matching ``</*>'' can be found for each ``<*>''. Comments of this type are remove before any files are included. So an <*><INCLUDE ...></*> will prevent the file from being included at all.

You could consider <*> </*> an HTML extension, but in fact it isn't because its action is performed before any Perl code starts execution.


Some extra ``HTML'' tags were added to make life still easier. Here is the complete list:

&lt;REDIRECT location&gt;

Print the string to redirect a user to another file. This is useful only if there is an <HTTP_HEADER> after the <REDIRECT> element.

For example:

 <IF $notok><REDIRECT>;<ENDIF>
 <TITLE>Parameters ok</TITLE>
 The parameters are ok.

Note that this performs the same function as the Redirect( $url ) function that is available in <PERL></PERL> sections.


Indicate to the browser that the current page should not be changed. This is useful only if there is an <HTTP_HEADER> after the <NOCHANGE> element.

For example:

 <IF $notchanged><NOCHANGE><ENDIF>
 <TITLE>Information updated</TITLE>
 The information is now updated.

Note that this performs the same function as the NoChange( ) function that is available in <PERL></PERL> sections.


Indicate to the browser that this document essentially contains frozen information. It allows the browser to re-display the document from its internal cache when the document is requested again and the server and browser agree that the document was not changed since it was stored in the browser's cache.

Note that this performs the same function as the FrozenContent( $lastchanged ) function that is available in <PERL></PERL> sections.

For example:

 <TITLE>Displayed from local cache</TITLE>
 This text will be displayed from a local cache when possible.

&lt;ACCESS_DENIED reason&gt;

Indicate to the server that access should be denied to the current Liz::Perl code. This is useful only if there is an <HTTP_HEADER> after the <ACCESS_DENIED> element.

For example:

 <IF $ENV{'REMOTE_USER'} ne 'liz'>
  <ACCESS_DENIED You're not Liz>
  <ACCESS_DENIED You're not really Liz>
 <TITLE>You're Liz</TITLE>
 Really you are!

Note that this performs the same function as the AccessDenied( $reason ) function that is available in <PERL></PERL> sections.


Flush any output that was saved since the last <FLUSH> (or the beginning of the document, or Flush( ) standard function) to the browser. Only makes sense in a ModPerl environment.

For example:

 <TITLE>Do we like you?</TITLE>
 This is displayed immediately using a single TCP/IP packet.
 <PERL>sleep 5</PERL>
 This is displayed after 5 seconds, again in a single TCP/IP packet.


Stop immediately with execution of the document. Usually used conditionally. Especially handy if there is an initial condition to which most of the rest the document is an <ELSE> to.

For example:

 <TITLE>Do we like you?</TITLE>
 <IF $wedontlikeyou>
  We don't like you!
 This won't be displayed if we don't like you.


Remove the cached version of the current file. Usually used in default page handlers only when the default page handler does not know what to do with it.

In this example, the first part of the final page remains ``live'', the second part is calculated only once.

 # If this page is valid (all numbered pages are assumed they are)
 #  Freeze the content of this page
 # Else (not a valid page)
 #  Make sure the browser also knows it's not ok
 #  Make sure this page is not cached

 <IF $SELF =~ m#(\d+)\.htm$#>
  <PERL>$R->status( 404 )</PERL>

 # The second part is only processed when creating the cached version
 # Do some general text

 <TITLE>Handling page $SELF</TITLE>
 Apparently the file $SELF
 does not exist, so the default page handler is generating this HTML
 output for you.

 # If this page is valid (note this is done once when creating cached version)
 #  Put some dummy text in there
 # Else (not a valid page when creating cached version)
 #  Put error message in there

 <IF $SELF =~ m#(\d+)\.htm$#>
  We will generate for ID "$1" now for you.
  You have tried to reach a page for which we cannot generate any
  sensible output.  To prevent this page from remaining in the cache,
  we will remove it from there without further ado.

&lt;PERL&gt; &lt;/PERL&gt;

The basic Liz::Perl extra: execute Perl code that is enclosed by the <PERL> </PERL> tokens. For example: <PERL>$score = 100</PERL>.

For example:

 <TITLE>Your score</TITLE>
 $score = 100 if $score<100;
 Your score is $score.

Note that you can display the value of a variable by just inserting it in the HTML code: no <PERL>print $score</PERL> is needed.


Because it is currently impossible to re-direct the functionality of the ``print'' command in Perl to an external routine, any prints inside <PERL> </PERL> sections should be replaced by ``Print''. Should ``print'' be used nonetheless, the following error code will be set:

 print trapped by operation mask at (eval XX) line YY.

&lt;INCLUDE filename&gt;

Include the contents of a file at that position in the HTML stream. Especially useful for headers and footers and the like.

For example:

 <TITLE>Your message</TITLE>
 <INCLUDE top>
 This is a message to the user.
 <INCLUDE bottom>

Note that files are relative to the file in which the INCLUDE occurs. Note also that it is possible to use the ``//file'' notation to indicate a file relative to the document root (as defined by $ENV{'DOCUMENT_ROOT'}) of the web server.

&lt;CACHE&gt; &lt;/CACHE&gt;

Any Pseudo-HTML between <CACHE> and </CACHE> is processed whenever a new cached version of the document is created, when the pseudo-HTML is converted to ``true'' Perl code. It can be used to execute certain CPU-intensive operations once for the lifetime of the cached version of the document. See Caching for more information.

&lt;IF condition&gt; &lt;ELSEIF condition&gt; &lt;ELSE&gt; &lt;ENDIF&gt;

Process the HTML conditionally. It basically offers the same capabilities as if() {, } elsif() {, } else { and } in Perl.

For example:

 <TITLE>Your score</TITLE>
 <IF $score==100>Your score couldn't be better!
 <ELSEIF 75<=$score>Your score is very good.
 <ELSEIF 60<=$score>Your score is sufficient.
 <ELSE>You need to work on your score.
 <FORM><TEXT score><SUBMIT "Set your score"></FORM>

Note that the condition can not have a ``>'' in it, as it would confuse the parser. Re-stating your conditions using a ``<'' solves that problem.

Also note that it is also legal to use </IF> as an alternative to <ENDIF>.

&lt;LOOP elements&gt; &lt;ENDLOOP&gt;

Process the HTML repeatedly within a loop structure determined by a list of values to be processed. It basically offers the same capabilities as foreach() { and } in Perl.

For example:

 <TITLE>Option List</TITLE>
 These are the available options:
 <LOOP qw(aap noot mies)><LI>$_<ENDLOOP>

Also note that it is also legal to use </LOOP> as an alternative to <ENDLOOP>.

&lt;WHILE condition&gt; &lt;ENDWHILE&gt;

Process the HTML repeatedly within a loop structure that remains active as long as a condition is true. It basically offers the same capabilities as while() { and } in Perl.

For example:

 <TITLE>Option List</TITLE>
 Options 1 through 99:
 <WHILE ++$counter<100><LI>$_<ENDWHILE>

Also note that it is also legal to use </WHILE> as an alternative to <ENDWHILE>.

&lt;NEXT condition&gt;

Continue with next iteration in a loop structure (either LOOP or WHILE). It basically offers the same capabilities as next in Perl.

For example:

 <TITLE>Option List</TITLE>
 Options 1 through 99 with triplets skipped:
 <OL><WHILE ++$counter<100>
 <NEXT $_%3==0>

&lt;LAST condition&gt;

Exit a loop structure (either LOOP or WHILE) prematurely. It basically offers the same capabilities as last in Perl.

For example:

 <TITLE>Option List</TITLE>
 Options 1 through 49:
 <OL><WHILE ++$counter<100>
 <LAST $_==50>

&lt; &gt;

Insert one or more non-breaking spaces (&nbsp;) into the HTML-stream. The number of non-breaking spaces is determined by the number of spaces between < and >.

For example:

  <TITLE>Non-breaking spaces</TITLE>
  This is at the start of the left margin<BR>
  < >This starts one character position to the right<BR>
  <          >This starts 10 character positions to the right

&lt;LET expression&gt;

For assigning a value to one or more variables, it is possible to use the <LET ..> pseudo-HTML code. This is a shortcut for a full-fledged <PERL>...</PERL> section. If more than one variable needs to be set, they must be seperated by comma's.

For example:

 <TITLE>Setting values</TITLE>
 <LET $score = 10>
 The score is $score.<BR>
 <LET $score++, $succeeded = 1>
 The score is now $score.
 <IF $succeeded><BR>You have succeeded!<ENDIF>

&lt;PRINT expression&gt;

Show the value of an expression that is not stored in a variable. It basically offers the same capabilities as print in Perl.

For example:

 <TITLE>Values squared</TITLE>
 <IF $value>$value**2 = <PRINT $value**2><P><ENDIF>
 <FORM>Enter a value: <TEXT value><SUBMIT "Square it"></FORM>

Note that you do not need the <PRINT> element if you just want to display the value of a variable: you can embed values of variables within HTML without any problems.


To make life easier on everybody, Liz::Perl changes the default action of the <FORM> element to ``post'' instead of ``get''. Therefore it is equivalent to write ``<FORM>'' and ``<FORM METHOD=post'' in Liz::Perl.

Furthermore, Liz::Perl also checks if there is a <FILE> element in the HTML stream. If so, the encryption type ``multipart/form-data'' is automatically added.

&lt;TEXT name&gt;

The basic input field for forms. Automatically displays the value if the variable specified already has a value.

For instance:

 <TITLE>Your last name</TITLE>
 <IF $name>
  Your last name is "$lastname".
 Please enter your last name: <TEXT lastname> <SUBMIT Send>

When executing this example, note that after the first time you have entered your name, your name will be filled in again at the second attempt.

Extra options, e.g. to limit the size of the input or to execute a JavaScript routine, can be added to the <TEXT name> token. For instance:

 <TEXT lastname SIZE=20 MAXLENGTH=64 onChange="CheckInput()"> 

&lt;RADIO name value&gt;

Show a radio-button with the given variable name and indicated value. Becomes automatically set if the value of the variable $name has the value ``value''.

 <TITLE>Your buttons</TITLE>
 Select a radio button: <RADIO b 1>1 <RADIO b 2>2 <RADIO b 3>3
 <SUBMIT Send>

The above example of course does nothing else then re-display the button you just selected. It is also possible to specify extra options, e.g to activate Javascript:

 <RADIO button 1 onClick="CheckRest()">

If you want to make a radio button always be selected, regardless of the value of the variable, then the string ``CHECKED'' can be specified like so:

 <RADIO button 1 CHECKED>

&lt;CHECK name value&gt;

Show a check-box with the given variable name and indicated value. Becomes automatically set if the value of one of the elements of the array @name has the value ``value''.

 <TITLE>Your checkboxes</TITLE>
 Select one or more checkboxes: <CHECK b 1>1 <CHECK b 2>2 <CHECK b 3>3
 <SUBMIT Send>

The above example of course does nothing else then re-display the checkboxes you just selected. It is also possible to specify extra options, e.g to activate Javascript:

 <CHECK box 1 onClick="CheckRest()">

If you want to make a check box always be selected, regardless of the value in the list, then the string ``CHECKED'' can be specified like so:


&lt;BUTTON name src width height&gt;

Show a button with the given variable name from the indicate source image. Apart from setting variables with the name name_x and name_y, the variable $action will also be set to the name of the button when clicked.

The width and height of the image are optional: if they are not specified, they will also not be specified in the resulting HTML-code.

 <TITLE>Your button</TITLE>
 <IF $action>Action = $action<P><ENDIF>
 <BUTTON yes yes.gif 69 24>
 <BUTTON no no.gif>

&lt;PULLDOWN name (values)&gt;

Show a pulldown menu (<SELECT> with <OPTION> sequence). Intended for quick generation of fixed option lists or option lists generated from a database.

 <TITLE>Your pulldown menu</TITLE>
 <IF $selection>You selected: $selection<P><ENDIF>
 Make your selection: <PULLDOWN selection qw(one two three)><SUBMIT Send>

Note that the value that is passed back to the script is the same as the string that is displayed.

It is also possible to specify the number of elements to be displayed at any one time (with SIZE=x``) and whether or not more than one option can be selected (''MULTIPLE``). Any extra HTML must be situated between the name and the values. The values must be surrounded by parentheses or as elements of the qw() function.

An extended format in which both the value and the string of each <OPTION> can be described, is also possible. Specify the word 'extended' as the first word of the options, and the options will be interpreted as ``value1 string1 value2 string2 etc...''.

 <TITLE>Your status</TITLE>
 <IF $status>You selected: $status<P><ENDIF>
 Make your selection:
 <PULLDOWN status SIZE="1" qw(extended 1 normal 2 extended 3 premium 4 sponsor)>
 <SUBMIT Send>

It is also possible to use the values from an array:


  @konijn = qw( extended 1 flapoor 2 langoor 3 knabbel 4 stamp );
  @konijn2 = qw( flapoor langoor knabbel stamp );

  <PULLDOWN konijn (@konijn)><BR>   
  <PULLDOWN konijn2 (@konijn2)><BR>   
  <BUTTON submit /button/100x15.submit.gif 100 15><BR>


In some cases, specifically when adding Javascript to the PULLDOWN element, the parser gets confused as to which is what. In that case you must use the extended form for the list specification, e.g.


  <PULLDOWN options OnChange="javascript:this('that')" LIST="qw(1 2 3 4 5)">


&lt;HIDDEN name value&gt;

Pass on a value to the next invocation of a script. You could consider this to be the same as the <TEXT> token, with one difference: as s user you cannot see the value and as a use you cannot alter it.

Its main use is to pass on values (for instance: names, numbers or session ID's) from one page to the next without the user having to be aware of it.

 <TITLE>Your hidden values</TITLE>
 <IF $notfirst>This is <B>not</B> the first time you're here.
 <ELSE>This is the first time you're here.
 <FORM><HIDDEN notfirst 1><SUBMIT "Click here"></FORM>

Please note that it is possible to change the value of a <HIDDEN> field with Javascript.

&lt;FILE name&gt;

Allow the user to specify a file to be uploaded. Currently only supported by Netscape and newer or patched MSIE's.

 <TITLE>Your file</TITLE>
 <IF $file>This is the contents of file $file_filename:
 Select file to upload: <FILE file><SUBMIT "Upload"></FORM>

Please note that Liz::Perl automagically adds the 'ENCTYPE=``multipart/form-data''' to the <FORM> token when a <FILE..> token is present in order for this to work.

Note that while the contents of the file is received in the variable specified with the <FILE..> token, the name of the file can be obtained with the variable $xxx_filename (where xxx is the name you specified with the <FILE..> token).

&lt;BENCHMARK identifying string&gt;

Generate benchmark information in HTML-comment style. When a <BENCHMARK> code is encountered, a string similar to:

 <!-- identifying string:  1 secs ( 0.14 usr  0.07 sys =  0.21 cpu) -->

will be placed in the output stream. This functionality can also be accessed from within Perl with the standard function Benchmark( $string ).

&lt;DIE reason&gt;

Special function for use within the ModPerl environment. Lets the Apache process that is handling the current request die after the request is completed. The string is logged to the error log. Otherwise has the same function as <STOP>.

&lt;PHP&gt; &lt;/PHP&gt;

When you are generating pages that are stored in HTML-files for later usage, it is possible to specify PHP code with the <PHP> </PHP> tokens. This is mostly to make sure that any references to variables are not evaluated when creating the HTML-file, but instead are left in there so that PHP can evaluate them when the HTML-file is accessed.

 <TITLE>Your PHP code</TITLE>
 <PERL>$score = 100</PERL>
 This score is fixed in HTML: $score.
 <PHP>$score = 50</PHP>
 This score is stored as PHP code: <PHP>echo $score</PHP>.

Note that if you inspect the actual HTML that is generated from the above code, you will see:

 <TITLE>Your PHP code</TITLE>
 This score is fixed in HTML: 100.
 <?$score = 50>
 This score is stored as PHP code: <?echo $score>.



&lt;INHERIT variables&gt;

Inherit one or more objects (usually variables) from the parent Liz::Perl object or from any other namespace if fully qualified. Mainly used when generating HTML-files from templates in a ModPerl environment or sending unique emails with the Liz::BulkMail package.

For example:

 <INHERIT $name $title $category $package::variable>
 <B>$name</B> belongs to category <B>$category</B>
 The value of \$variable is: $variable.


These methods are usually specified in the Apache configuration as a filter applied to one of the steps from the request to the server to sending the data-stream to the client.


Generic Authentication handler for use within Liz::Perl activated scripts. It allows access checks within the Liz::Perl code itself rather than before any of the Liz::Perl code is actually executed.

Only sets the environment variable ``$ENV{'REMOTE_USER_PASSWORD'}'' with the password that the user gave. When this authentication module is activated, the environment variable ``$ENV{'REMOTE_USER'} will be set if access has been denied at least once.

To disallow access, call the subroutine AccessDenied and optionally give a reason why access was denied (this will be recorded in the server's error log).


In the Apache configuration:

 <Directory /export/home/local/www/intranet>
 AuthName          xxLINK Intranet
 AuthType          Basic
 PerlAuthenHandler Liz::Perl::Authenticate
 Require           valid-user

In the document that is to be protected:

 AccessDenied( 'No username given' ) unless $ENV{'REMOTE_USER'};
 AccessDenied( 'No password given' ) unless $ENV{'REMOTE_USER_PASSWORD'};
 AccessDenied( 'Not Liz' ) if $ENV{'REMOTE_USER'} ne 'liz';
 AccessDenied( 'Not really Liz' ) if $ENV{'REMOTE_USER_PASSWORD'} ne 'zippo';

The first line checks whether there is a user name given at all, and denies access if none was given. Line 2 does the same check, but for the password. The third line checks whether the user is valid and if not, denies access. Line number 4 checks whether the password is ok, and denies access if it is not.


Indicate that each page which is requested on a server that is Liz::Perl enabled, will automatically send a cookie at the first request on the site (as determined by the referer: header). The value of the cookie is a random string, which e.g. can be used as a key for keeping session information (the Liz::Session module knows how to handle this).

The cookie sent is a temporary cookie, which is only saved as long as the browser session is active. It thus also works with browsers that have the permanent cookie-file disabled.

The cookie sent has a path specification ``/'', so that the cookie refers to the entire web-site.

If automatic session cookies are activated, then the field AUTOMATICSESSIONCOOKIE of the %ENV hash will be filled with the cookie just received from the browser. If the cookie was not sent yet, or was not accepted by the browser, then this key will not be set.

For the cases where the cookie was not set yet, or will not be set because they are ignored by the browser, you can also use the environment variable $ENV{'VISITORID'}. This is a 32-byte string that attempts to create a unique ID for the visitor, using such information as IP-number, proxy, user-agent and language preferences. Although this number is fairly unique, it is definitely not guaranteed to be unique during any length of time. But it can be used if cookies are disabled, or when going from the first page on a website (when no cookie is available yet) to the second (when the cookie is returned by the browser). This approach is used by the Liz::Session module.

The visitor ID as well as the cookie string can also be logged in the standard Apache logs with the following custom log format: ``%{VISITORID}i'' (without quotes) for the visitor ID and ``%{AUTOMATICSESSIONCOOKIE}i'' (without quotes) for the cookie of the user, thereby generating a clicktrail that can be used by logging programs.

To activate automatic session cookies, one must specify this routine as the PerlHeaderParserHandler in the main part of the configuration file:

 PerlHeaderParserHandler        Liz::Perl::AutomaticSessionCookie


Subroutine to check the validity of the Apache->request object. Logs error if not passed as a parameter and/or not able to recover the Apache->request object. Attempts to let the Apache child commit suicide if no request object could be found (in which case we're probably really screwed).

This subroutine is intended to be used by Perl*Handlers that need access to the request object to perform correctly, in Liz::Perl e.g. Authenticate and AutomaticSessionCookie.

Input Parameters

 1 variable with the current request object
   (must be variable: a recovered request object will be placed in there)
Output Parameters

 1 flag if an unrecoverable error has occurred
   (undef: no error)

  my ($r) = shift
  return SERVER_ERROR if Liz::Perl::CheckRequestObject( $r );

Default Page Handler

In a ModPerl environment, it is possible to define a default page handler, a Liz::Perl script that is executed automatically if the requested page does not exist. This default page handler can then decide whether to generate HTML output for the requested page, and store it in the ModPerl cache when necessary.

To install a default page handler in Liz::Perl, you must add the following line to the Apache configuration of the Virtual Host for which the virtual page handler should operate:

 B<ErrorDocument    404    /.lizperldefault.lp>

Although you only define the ErrorDocument only once for the entire Virtual Host, Liz::Perl will search from the directory in which the requested file should reside, until the document root directory, for occurrences of the file ``.lizperldefault.lp''.

Suppose the following document tree exists:


A request to ``/home.lp'' would be handled by the file ``/home.lp'', because that exists.

A request to ``/gone.htm'' would be handled by ``/.lizperldefault.lp'' because ``/gone.htm'' does not exist.

A request to ``/documents/english/12345.htm'' would be handler by ``/documents/.lizperldefault.lp'', because there is no default page handler in the ``/documents/english/'' subdirectory, but there is a default page handler in ``/documents''.

However, a request to ``/documents/dutch/12345.htm'' would be handled by the default page handler in ``/documents/dutch''.

The Perl-output of the Default Page Handler is stored in the Liz::Perl cache (see CacheDirectory) as if the page existed. The next time the same non-existing page is requested, then the Perl-version from the cache will automatically be used, thus reducing the overhead of re-creating that page.

Together with a smart use of FrozenContent( $lastchanged ), ContentLength( $length ) and <CACHE>...</CACHE> it is possible to create a HTML-file that appears to the browser as completely fixed content, and which takes almost no extra CPU to serve to the browser.

See Output Manipulation for an example of this.

You can use this approach to the extreme. If you have no HTML-files in the document root apart from a single Default Page Handler, then you have in fact created Virtual File System in which each page is generated from information elsewhere, e.g. an SQL-database.


These methods are usually called in the ModPerl startup-script that is automatically started when Apache is started.


This class method defines a UNIVERSAL::AUTOLOAD routine that will catch any references to non-existing subroutines. This is particularly important in the ModPerl environment where a reference to a non-existing subroutine may cause the httpd server to spin into oblivion, possibly taking the whole physical server with it.

This method is usually called in the startup perl script.




Specify the directory that should match the path of any Liz::Perl script in the ModPerl environment. Optionally specify the directory in which the Perl scripts should be stored.

This class method should be called in the startup perl script of ModPerl, so that it can be shared automatically by all the children and/or threads of Apache. This class method also clears the directory of any files stored in there to insure they are up-to-date unless this is inhibited.

Input Parameters

 1 directory to match Liz::Perl scripts with
 2 directory to store cached Perl scripts in
   (default: $matchdirectory/.lizperlcache/`hostname`)
 3 inhibit clearing of the cache
   (default: clear cache)

 Liz::Perl->CacheDirectory( '/export/home/local/www' );

or, not clearing the cache when an automatic restart at midnight:

  '/export/home/local/www','',Liz::Timestamp2Date('%R') eq '00:00' );


Specify the filename of which the cached version should be removed from the cache. This is particularly important when the database contents of a cached file with <CACHE>...</CACHE> is updated. A call to this class method with the name of the file will cause the next user to visit that page to create a newly cached version.

This class method should usually be called only in a maintain section of web-site.

Input Parameters

 1..N filename of which the cached version should be deleted
      (may be relative and contain wildcards)

 # Remove the current file from the cache (e.g. when using virtual files)

 Liz::Perl->RemoveFileFromCache( $SELF );

or: when a maintain script should update its own ``normal'' version:

 # obtain filename of maintain (could be SELF with special options)
 # remove the maintain part from the filename (now the "normal" version)
 # remove the cached version of the file

 $filename = $SELF;
 $filename =~ s#maintain/##;
 Liz::Perl->RemoveFileFromCache( $filename );


Indicate that the compiled source code should be cached inside the Liz::Perl objects and be executed from there. By default, only the source is cached in the Liz::Perl objects and re-compiled before each Execute.




There is only one constructor in the Liz::Perl package: new.


Create a new Liz::Perl object.

Input Parameters

 1 filename or HTML stream to be executed
 2 flag: whether to only execute after __END__
   (default: undef=all, 0=force as HTML, 1=execute after END/DATA)
 3 filename to store in $SELF if HTML stream specified
   (default: $0)
Output Parameters

 1 instantiated object

 $lp = new Liz::Perl( $filename );


Several options can be set before the code in the Liz::Perl object is executed.


Set to output the resulting HTML to an external file.

Input Parameters

 1 name of file to write output to
   (default: STDOUT)
Output Parameters

 1 the object itself (handy for one-liners)

 $lp->File( "/usr/var/www/entry$loop.htm" );

or shorter:

 $lp->File( "/usr/var/www/entry$loop.htm" )->Execute;


Set to return the resulting HTML when Execute is called.

Output Parameters

 1 the object itself (handy for one-liners)

 $html = $lp->Execute;

or shorter:

 $html = $lp->Return->Execute;


Set to output HTML to STDOUT. This is the default when a Liz::Perl object is created.

Output Parameters

 1 the object itself (handy for one-liners)


or shorter:

 $html = $lp->Normal->Execute;


Set to generate PHP compatible HTML code. This is usually done when pre-generating large numbers of files that need some limited form of interactivity such as PHP.

Output Parameters

 1 the object itself (handy for one-liners)


or shorter:

 $html = $lp->PHP->Execute;


Execute the Perl code associated with the Liz::Perl object. Output will be sent to STDOUT unless otherwise indicated with a prior call to method File or Return.

Output Parameters

 1 HTML that was created if return of contents was requested, else undef

 $error = $lp->Execute;



Return the Perl representation of the source of the object.

Output Parameters

 1 Perl source code

 $perl = $lp->Perl;



*** OBSOLETE ***

Please use Liz::Calc::GetImageDimensions instead.


Convert an HTML-stream with Liz::Perl specific codes and return the resulting Perl code that is ready for execution. This is a routine for internal use only mostly.

Input Parameters

 1 HTML-stream or filename to be processed
   (default: STDIN)
 2 flag: type of Perl to create
   (default: ordinary Perl script output)
 3 filename to which source if relative
   (default: file in current directory)
Output Parameters

 1 Perl-script

The following types of Perl script can be generated:

  0 generate ordinary Perl script ( print )
  1 generate Perl with PHP in it (PHP sections have variables escaped)


Inherit one or more objects (variables, arrays, hashes or subroutines) from the parent Liz::Perl process or from any namespace if fully qualified objects are specified.

Input Parameters

 1..N objects to be shared

 Inherit( qw($score @array %hash &routine $package::variable) );


The Liz::Perl module is prepared for usage with ModPerl.

Apache configuration

Specifying this module as a Perl Handler will cause all files that match the file/directory specification to be processed by Liz::Perl automatically.

For instance, specifying:

 <Files *.lp>
 SetHandler     perl-script
 PerlHandler    Liz::Perl

will cause all files with the extension .lp to be processed by Liz::Perl. A specification of:

 <Location /cgi-bin>
 SetHandler     perl-script
 PerlHandler    Liz::Perl

will cause all files in the /cgi-bin directory to be processed by Liz::Perl.

Special variables

The following special variables are available in the ModPerl environment:

 $R           the Apache::Request object for this file
 $self        the Liz::Perl object of the file itself
 $SELF        the name of the file being processed
 $BUFFER      the output since last <FLUSH> (or beginning of script) if no automatic buffering is active
 $GETPOSTDATA reference to the raw input received from the browser


A very simple caching mechanism is provided under ModPerl. If a template has been processed, a reference to the Liz::Perl object and the time and date when the (main) template was last changed, is kept. Whenever the same template is processed, it is first checked if there is a copy already in the cache, and if so, if the last modified date and time of the file is the same as before, the cached Perl-code is used instead of creating a new copy.

By caching the Perl-code of the templates up to 95% of the CPU is saved by not having to re-create Perl-code from the template.

However, during development of templates this may cause problems when an INCLUDEd file is changed without changing the main template. There are currently only three solutions to this:

 1. Remove the file from the cache with Liz::Perl->RemoveFileFromCache( filename ).
 2. Change the last modified time of the main template.
    This can e.g. be done with the "touch" command.
 3. Restart the ModPerl-enabled Apache daemon.
    This effectively clears all caches.

This caching event can also be used to save on CPU: suppose a part of the template contains expensive CPU calculations (e.g. extensive database access to create a pulldown menu of which the options reside in the database) of which the result is the same for every visitor of the page, then the <CACHE>...</CACHE> pseudo-HTML codes can be used. Any code between <CACHE>...</CACHE> is only executed whenever a new cached version of the template is created (e.g. after a server restart or when the file containing the template has been changed).

Server Push

It is also possible to perform server push actions with Liz::Perl when running under ModPerl. For that, two special subroutines are available in each Liz/ModPerl document:

ServerPush( $MIMEtype,$filename )

Subroutine ServerPush() takes two arguments. The first is the default MIME-type that each frame of the server push will have unless changed by a call to ContentType(). The default MIME-type is 'text/html'.

The second argument is the filename the document should have (also known as the content-disposition). No content-disposition info will be sent if not specified.

After subroutine ServerPush is called, any output will not be sent directly but be kept in a buffer until function NextFrame() is called.

NextFrame( $sleep )

Subroutine NextFrame() takes one argument: the number of seconds to sleep after the current frame is finished. No sleep will occur if the variable is not specified. It ends the current frame by sending all accumulated output to the client, optionally wait a while and start a new frame.


In this example all .GIF files in the current directory are sent to the user in one second intervals. It is assumed that all images have the same size, most browsers do not how to handle differently sized images in a Server Push stream.

 ServerPush( 'image/gif' );
 foreach( <*.gif> ) {
   AsIs( $_ );
   NextFrame( 1 );

Output Buffering

Normally, the output of each Print() statement (or each piece of uninterrupted HTML-code) is buffered before being sent to the browser. This buffering ensures that TCP/IP packets are filled as good as possible before being sent, thereby optimising throughput on connections with high latencies.

However, this can cause a problem when you would want the text just before a long process to be sent to the browser before the long process starts.

To control the TCP/IP packets being sent to the browser, it is possible force the output to the browser with the standard function Flush( ) and the pseudo-HTML code <FLUSH>. When the pseudo-HTML code <FLUSH> occurs within the Liz::Perl code, all output will be saved internally until either Flush() or <FLUSH> is encountered. When the Liz::Perl code is finished, then the remaining data will be automatically sent to the browser.


 <TITLE>Simple sleep example</TITLE>
 This text appears on the screen immediately<BR>
 <PERL>sleep 5</PERL>
 And this text after 5 seconds.

With the <FLUSH> the first text appears, then 5 seconds nothing, and then the second text. Without the <FLUSH> nothing would appear on the screen until after the 5 seconds

Output Manipulation

Any output that is buffered when <FLUSH> is active, is available to the script in the variable $BUFFER. This variable, and therefor the output to the browser, can be manipulated from within the script before actually being sent to the browser.

This allows changes to be made to the output, e.g. adding a session key to each URL in the output, or anything else that you would like to do.


Take this HTML sequence:

 This is a bad example of output buffering.
 <PERL>$BUFFER =~ s/bad/good/s</PERL>

This will be send to the browser as:

 This is a good example of output buffering.

Note that the word ``bad'' was changed to the word ``good''.

It can also be used to calculate the content-length of the page before being sent to the browser. This can cause a significant speed improvement because then a connection can be kept open with the browser if Keep-Alive is active.



 # Start the page

 <TITLE>Handling page $SELF</TITLE>
 Apparently the file $SELF
 does not exist, so the default page handler is generating this HTML
 output for you.

 # If it is a valid page for automatic generation
 #  Show valid text (just a dummy here now)

 <IF $SELF =~ m#(\d+)\.htm$#>
  <PERL>$ID = $1</PERL>
  We will generate for ID "$ID" now for you.

 # Else (not a valid page)
 #  Tell the user so, not that the file is not being uncached just yet

  You have tried to reach a page for which we cannot generate any
  sensible output.  To prevent this page from remaining in the cache,
  we will remove it from there without further ado.

 # Calculate the output that we have so far
 # Prefix it in the buffer, note the ! in the PERL code to prevent interpretation now

 $length = length($BUFFER);
 $BUFFER = "<!PERL>ContentLength( $length )<!/PERL>$BUFFER";

 # If there is an ID, so it was a valid page
 #  Make sure the content will be frozen as far as the browser is concerned
 # Else (not a valid page)
 #  Make sure it will be marked as an error and that it will not remain in the cache

 <IF $ID>
  <PERL>$BUFFER = "<!PERL>\$R->status( 404 )<!/PERL><!UNCACHE>$BUFFER"</PERL>

This causes a completely fixed HTML-file to be generated for valid pages, including a Content-Length: header (so that the connection with the browser can be kept alive) and a Last-Modified: header so that the browser can do a conditional GET when it has the page stored in its local cache.


Depending on the contexts, several steps are taken from the Liz::Perl script (HTML with pseudo HTML-codes) until completely generated HTML (or any other output, for that matter, such as GIF's).

Basic conversion

The basic conversion steps are as follows:

1. read in the original Liz::Perl script (either from a file or as a parameter).

 <*> This is a pseudo-HTML comment</*>

 # This is a Perl-style comment

 <PERL>$score = 100</PERL>
 <IF $score == 100>
  Not so good!
 <INCLUDE footer>

2. expand all <INCLUDE file> pseudo HTML-code recursively until there are no <INCLUDE file> codes left. Remove any <*> </*> comments before inserting included code.



 # This is a Perl-style comment

 <PERL>$score = 100</PERL>
 <IF $score == 100>
  Not so good!
 <CENTER><SMALL>(C) 1996-1999 xxLINK Internet Services</SMALL></CENTER>

3. process any <MACRO...> codes and replace any macro's by their content.


 # This is a Perl-style comment

 <PERL>$score = 100</PERL>
 <IF $score == 100>
  Not so good!
 <CENTER><FONT SIZE="1">(C) 1996-1999 xxLINK Internet Services</FONT></CENTER>

4. process any code between <CACHE>..</CACHE> by doing a full conversion, as if the code is a complete Liz::Perl script of its own, and insert the output at that location in the text. This is skipped in this example for the sake of simplicity.

5. convert all special pseudo HTML-codes to <PERL>,,,</PERL> equivalents, e.g an <IF $condition> becomes <PERL>if( $condition ) {</PERL> and an <ENDIF> becomes a <PERL>}</PERL>.


 # This is a Perl-style comment

 <PERL>$score = 100</PERL>
 <PERL>if( $score == 100 ) {</PERL>
 <PERL>} else {</PERL>
  Not so good!
 <CENTER><FONT SIZE="1">(C) 1996-1999 xxLINK Internet Services</FONT></CENTER>

6. Remove any superfluous </PERL><PERL> codes, as they are not needed and most likely generated from other pseudo HTML-codes.


 # This is a Perl-style comment

 <PERL>$score = 100;
 if( $score == 100 ) {</PERL>
 <PERL>} else {</PERL>
  Not so good!
 <CENTER><FONT SIZE="1">(C) 1996-1999 xxLINK Internet Services</FONT></CENTER>

7. Convert all text between </PERL> and <PERL> to Print(``text'') and remove the <PERL> and </PERL> pseudo HTML-codes.

 Print( "<HTML><BODY>

 # This is a Perl-style comment

 "); $score = 100;
 if( $score == 100 ) { Print("
 "); } else { Print("
  Not so good!
 "); } Print("
 <CENTER><FONT SIZE="1">(C) 1996-1999 xxLINK Internet Services</FONT></CENTER>

8. Convert any HTML-codes that start with <! to their equivalent without the !. This is skipped in this example for the sake of simplicity.

9. Replace any one-line comments (lines that start with ``# '') by an empty line. This effectively removes the comment from the code, but keeps line numbering intact.

 Print( "<HTML><BODY>


 "); $score = 100;
 if( $score == 100 ) { Print("
 "); } else { Print("
  Not so good!
 "); } Print("
 <CENTER><FONT SIZE="1">(C) 1996-1999 xxLINK Internet Services</FONT></CENTER>

The result of this basic conversion is available with the Perl method. Internally, a call to this method will perform this conversion if it hadn't been done already.

The Perl code that results from the basic conversion can be executed with the Execute method. The output can either be sent to standard output (which is how it is used in a cgi-bin environment), or to a file (by calling the File method beforehand) or be returned to the calling routine (by calling the Return method beforehand).

ModPerl execution without file-caching

The Liz::Perl module provides a generic PerlHandler that will cause the file that is requested, to be automatically converted into a Liz::Perl object, executed and its output sent to the browser. A very simple caching mechanism is then still in use: each Apache child in which Liz::Perl is activated, contains its own in-memory cache of Liz::Perl objects of file that were handled by that particular child.

This causes any subsequent requests to the same file to be handled much more quickly becomes no conversion processes are necessary anymore: the Perl-code can be executed immediately.

Although this provides some speed increase, it still needs to re-interpret the script for each child, which can be wasteful on busy sites. Therefore ModPerl execution with file-caching provides a much better performance gain.

ModPerl execution with file-caching

By calling the class method CacheDirectory in the servers startup perl file (as specified by PerlRequire in the Apache configuration), the Liz::Perl module knows where to store the Perl representation of Liz::Perl scripts. The following steps are then taken if the script exists:

1. check if there is a in-memory instance of a Liz::Perl object for that file (just as if no file-caching is active). If so, and the version was cached after the file was last changed, use that object and skip to step 5.

2. check if there is a Perl presentation of the file in the file-cache. If it exists, and it was saved after the file was last changed, create a Liz::Perl object for it using that Perl representation, save it in-memory and skip to step 5.

3. create a new Liz::Perl object from the file and save it in-memory for future accesses.

4. create the Perl presentation of the file and save that presentation at the location indicated by CacheDirectory and the name of the file.

5. execute the Liz::Perl object, sending the output to the browser directly.

This is pretty straightforward and creates a good response time on even very busy websites were all pages are handled by Liz::Perl. However, in many cases, especially on database-driven websites, a developer would either have to generate a separate page for each database record, or have to generate each page each time it is requested from the database. Both have their advantages and disadvantages.

The Liz::Perl module provides an extra mechanism for these cases, which is called a Default Page Handler. Essentially this allows the developer to cache non-existing files in the Liz::Perl file-cache. Basically there is only a change in step 3 in the above 5 steps:

3. create a new Liz::Perl object from the default page handler (.lizperldefault.lp), set the filename for storage of the Perl representation to the non-existing file (so that it appears from file-cache that it does exist) and save it in-memory for future access.

In this manner, it is possible to generate a page when a browser requests it (and it doesn't exist yet) while being able to quickly serve the same page in a future request, because the Perl-presentation of the page was already saved in the file-cache.


Elizabeth Mattijsen ( )


(C) 1996-2000 International Network Consultants


Version 4.81, 13 May 2000

Fixed problem with Redirects that would in some cases not work in Internet Explorer: in that case redirects are handled in HTML. Also finally got the error message to appear correctly when attempting to redirect when output was already sent.

Version 4.80, 7 May 2000

Added automatic setting of content-type 'text/vnd.wap.wml' for WML pages. Triggered by the occurence of the <wml> tag.

Version 4.79, 30 March 2000

Disabled in RAM caching of Liz::Perl objects in the ModPerl environment to check out vague reports of incorrect caching.

Version 4.78, 28 March 2000

Fixed problem in method Perl which would produce an internal server error in the ModPerl environment if it was not possible to create a lock-file.

Version 4.77, 27 December 1999

Method File now also allows specification of filenames in the form ``//dir/file'' where the // indicates the contents of $ENV{'DOCUMENT_ROOT'}.

Fixed problem in Execute which would cause an execution error if the specified file did not exist.

Version 4.76, 15 December 1999

Changed <MACRO ..> such that parameters are only recognized if they are between parentheses. If not, then no match occurs and the string is not expanded. This change prevents a match with almost all existing scripts that would break if the parentheses rule would not be applied.

Version 4.75, 14 December 1999

Introduced the <LET expression> pseudo-HTML code for quickly assigning values to variables.

Improved the <MACRO ..> feature so that ``recursive'' macro definitions (such as <MACRO form <FORM ACTION='file.lp'>> are properly handled.


If a file contains e.g. a definition <MACRO form <FORM ACTION='wop.lp'>> and the rest of the file contains both strings in the form <FORM> and <FORM TARGET=``_top''>, the second one will now be converted improperly because before it would not be touched by macro conversion, but now it will be considered a macro with parameters, which will cause an error in the Perl compilation phase.


Version 4.74, 13 December 1999

Standard function HTML( $filename )now prints the result when called in a void context.

Added possibility to specify parameters with the still undocumented <MACRO ..> feature in the internal subroutine HTML2Perl.

Fixed problem in HTML( $filename ) which would cause extra information to be shown when used in a <PRINT ..> HTML code.

Version 4.73, 6 December 1999

Changed ordinary open() to IO::File->new for more consistency and to avoid namespace problems that might occur.

Changed internal routine HTML to better check whether a valid Liz::Perl object was created.

Version 4.72, 4 December 1999

Implemented first version of file locking to prevent race-conditions in creating the Perl-source code from changed templates on very busy sites. Mainly changes in subroutines ModPerlCache and the Perl and CacheDirectory methods.

Version 4.71, 3 December 1999

Added a new pseudo-HTML feature for non breaking spaces: < >.

Changed the base namespace from 'LizPerlHTML' back to 'Liz::Perl::HTML', which should fix the problems some external modules had (e.g. Liz::Session).

Put module name between quotes to fix obscure bug in Perl 5.005x under ModPerl in subroutines HTML, HTML2Perl, handler, ModPerlCache, RUnCacheLP and AsIs.

Version 4.70, 18 November 1999

Fixed problem introduced with the namespace change of yesterday: any Liz::Perl scripts within other Liz::Perl scripts just wouldn't work. This still didn't fix the obscure namespace problem.

Version 4.69, 17 November 1999

Changed the namespace in which scripts are executed, which seems to fix an obscure problem with other Liz::xxx modules.

Fixed potential problem in internal subroutine HTML2Perl when a included file would have CRLF as line-delimiters.

Version 4.68, 10 November 1999

Fixed type in error handling (edfined->defined). Spotted by RF Lens.

Version 4.67, 7 November 1999

Fixed internal subroutine SelectLP so that values of options are placed between double quotes as they should be.

Version 4.66, 31 October 1999

Internal subroutine IncludeFile now adds an error message to the <INCLUDE > token, as well as a fully qualified filename if an error occured obtaining the file to be included. Now also handles include files that have regular expression sensitive characters, e.g. ([]).?*, in them.

Version 4.65, 20 October 1999

Added ``$'' as allowable character in the variable name of a <TEXT...> HTML code. This should make it easier to work with variable variable names in loops.

Added documentation to the PULLDOWN HTML element of how to handle additional Javascript HTML.

Version 4.64, 30 September 1999

Now no longer adds Exporter to ISA: it wasn't necessary.

Added subroutine CheckRequestObject to facilitate checking of screwed requests.

Adapted checking and error logging for missing request object in AutomaticSessionCookie and Authenticate.

Version 4.63, 4 September 1999

Fixed problem in internal subroutine IncludeFile which would cause MACRO definitions to get lost if the included file was in DOS-format (using CR/LF as line endings).

Version 4.62, 30 August 1999

Added class method CatchMissingSubs for catching references to non-existing subroutines in the ModPerl environment.

Version 4.61, 26 August 1999

Support for the Die( $string ) function and <DIE> HTML tag added.

If an error occurs within the ModPerl environment, the child is now killed to prevent a screwed up child from creating even more errors in the future. This particularly fixes the problems of errors because of stale database handles.

Conversion to new source typography completed. Cleaned up some minor things along the way.

Removed ``o'' from almost all m// and s/// as they were bogus (Randall: ``severe cargo-cult programming! ;-)

Version 4.60, 24 August 1999

Added configurable support for compiled code cached in the object. Class method CodeCached now allows you to indicate this when starting up the ModPerl server.

Changed benchmark routine at the end of a page to be aware of the newest, which talks about ``wallclock'' seconds.

Version 4.59, 17 August 1999

Fixed problem with bare <BENCHMARK> and <FROZENCONTENT> HTML tags not being converted: introduced on August 10 (4.57).

Version 4.58, 11 August 1999

Changed the ModPerl error handling so that the size of the data is limited as such:

 - 32K HTML output
 - 32K Perl source code
 -  2K $Liz::SQL::QUERY
 -  2k $Liz::SQL::ERROR

This should create a little smaller emails when the script for some reason ``exploded''.

Version 4.57, 10 August 1999

Speeded up HTML2Perl by combining multiple s///'s into a single s///. Preliminary benchmarks indicate a gain of .01 CPU second per K scanned template on a PII 233 Mhz. For most normal files, this provides a reduction of CPU usage of 80% for the initial conversion of a template to Perl source code.

Version 4.56, 6 August 1999

Fixed some problems in HTML2Perl with regards to the <TEXT> pseudo-HTML.

Version 4.55, 28 July 1999

Perl source code is no longer included as an attachment, but now in the body of the email message that is sent when an error has occurred. This should reduce waiting times with mail programs such as Eudora, that handle a high number of identically named files badly.

Version 4.54, 14 July 1999

Standard function Redirect () now defaults to ``/'' if no URL is specified.

Version 4.53, 8 July 1999

The internal subroutines QuoteLP, MakeInputLP and PrintInputLP are no longer imported into the Execute namespace. This should reduce the memory footprint and cpu usage a bit. This could probably be done to many other routines that are now imported into the script's namespace.

Now fully qualified variables can be specified with the <INHERIT> pseudo-HTML code.

Started with conversion to new source typography.

Version 4.52, 7 July 1999

Added special section for display of standard variable $GETPOSTDATA in the error messaging section of the ModPerl handler.

Version 4.51, 6 July 1999

Changed functionality of standard function ContentType( ) so that it will default to MIMEtype 'application/octet-stream' if no MIMEtype is specified.

Version 4.50, 28 June 1999

Reversed change of 4.49 to Execute: die() or Apache->exit both cause an execution, thus crippling Redirect(), Stop(), Accessdenied() and NoChange().

Changed all occurences of Apache->exit to die(), in the hope this would fix the above problem. Adapted Execute so that a ``Just Stopping'' die message also flushes anything that is in the frame buffer.

Version 4.49, 26 June 1999

Changed Execute so that a compiled version of the Perl-script is first created and placed in the object. Then the compiled version stored in the object is executed. The next time the same Liz::Perl object is executed, the compiled version will be used immediately.

This should specifically speed up generation of HTML-files significantly. It should also speed up the processing of often-visited pages in the ModPerl environment, at the expense of using more memory (adapting Apache's MaxRequestsPerChild parameter may be required if Apache::SizeLimit is not used).

Version 4.48, 15 June 1999

Fixed problem with <BENCHMARK ...> and Benchmark() function: they were not working since probably version 4.44.

Version 4.47, 6 May 1999

Changed the functionality of AutomaticSessionCookie. Now, only one cookie will be sent to the browser while at the same site (as determined by the Referer: header). If that cookie is ignored, then only the visitor ID (an attempt at a unique ID depending on IP-number, proxy and user-agent, among others) should be used.

Version 4.46, 4 May 1999

Fixed problem with <FLUSH> and Flush( ) that would cause extra header setting before the first flush to be ignored.

Fixed problem with RemoveFileFromCache that was introduced on May 1st. Any call with a fixed parameter would abort the request.

Version 4.45, 3 May 1999

Fixed problem with Default Page Handlers if one or more directories did not exist in the request (which caused them to disappear in the PATH_INFO of the original request).

Added significant documentation for Default Page Handlers, Virtual File System and HOW DOES IT WORK?.

Fixed problem with ErrorDocument handlers that are not Liz::Perl Default Page Handlers.

Version 4.44, 1 May 1999

First version of Liz::Perl <Default Page Handler>s added.

Benchmark info in ModPerl is not shown now if a content length was specified.

Fixed problem with benchmark info in ModPerl sometimes not appearing.

It is now also possible to use output manipulation when just returning output (either directly with Return or indirectly by using the <CACHE> and <UNCACHE> pseudo HTML codes) and when just printing the output, either directly or to a file (File). In all cases, the HTML output so far is available to the script in the $BUFFER variable.

Pseudo-HTML code <UNCACHE> and standard function UnCache( ) added. Remove the current file from the cache directory. Mainly used in default page handlers only.

Class method CacheDirectory now accepts a third input parameter to inhibit automatic clearing of the cache.

Class method RemoveFileFromCache now also accepts wildcard specifications, which allow e.g. allow all cached files of a directory to be removed.

Version 4.43, 21 April 1999

Specific debug data, such as last query and error message, is now seperately listed for the Liz::SQL module in the error reporting.

When an error occurs, the error report now also shows the error string of the module when available.

Version 4.42, 19 April 1999

Fixed problem with ``print'' after ``}'' in HTML2Perl.

Version 4.41, 14 April 1999

Prevented error message ``use of initialized value'' when used outside of ModPerl context with regards to $ENV{'DOCUMENT_ROOT'}.

Fixed yet another 2 cases of ``print'' to Print translation.

Version 4.40, 13 April 1999

Attempting to <REDIRECT...> or Redirect() in a ModPerl environment after output was already sent, will cause an error message to be presented in the HTML stream, rather than just sending the cryptic HTTP header into the HTML stream.

Bare <LOOP> pseudo-HTML is now also allowed.

Version 4.39, 12 April 1999

Re-did way in which recursive Liz::Perl calls are handled. Instead of a list, indexed by LEVEL, key global variables are now saved and restored locally in Execute.

Class method RemoveFileFromCache now accepts more than one file to be removed from the cache.

Version 4.38, 11 April 1999

Added new class method RemoveFileFromCache: removes the cached version of a file from the cache, causing the next visitor to create a new cached version of the file.

Fixed problem with CRLF in template files: any CR's are now removed from template files also, preventing any problems with files FTP'ed to the server in BINARY mode.

Added new <CACHE>..</CACHE> Pseudo-HTML. Any HTML (or <PERL>...</PERL> code) that is located between <CACHE>...</CACHE> is processed whenever the HTML template is processed, i.e. after a server restart or when the main HTML file is changed. This allows CPU intensive operations, e.g. on databases, to be performed once instead of each time the page is requested.

Version 4.37, 10 April 1999

Fixed problem with recursive use of Liz::Perl: all global variables that matter are now indexed according to their level of recursion to prevent unwanted interaction between the invocations.

Output in the ModPerl environment is now buffered automatically to fill up TCP/IP packets as full as possible. Explicit flushing of buffered output of course remains possible with <FLUSH> and Flush();

Changed ``inline'' number of packet calculations by references to Liz::Calc::Packets.

Now outputs warning to the error log if no request object available in the AutomaticSessionCookie handler.

Now deletes Cookie altogether if AutomaticSessionCookie was the only cookie sent by the browser.

Version 4.36, 9 April 1999

Dummy cookies now also include hashed Accept-Charset information, as that is probably also an individual setting of the browser.

Now also lists the process number in the final benchmark message in a ModPerl environment.

Version 4.35, 6 April 1999

The AutomaticSessionCookie handler now attempts to create a unique dummy cookie for those users it finds are not receiving or sending cookies.

Undefined list values are no longer listed in the error email that is sent whenever an error occurs in a Liz::Perl environment.

Version 4.34, 5 April 1999

The referring page is now put in the header of the error email, so that it can be easily seen whether the problem occurs when the site is first visited, or when the user had been on the site already.

Version 4.33, 4 April 1999

Pseudo HTML-codes <RADIO..> and <CHECK..> now allow the word ``CHECKED'' to be specified to bypass the check logic and always mark the choice as selected.

Version 4.32, 3 April 1999

When an error occurs when output buffering is in effect, then the output that was saved, will first be sent to the browser before the error output. Before, the buffered output would be lost.

New special ModPerl variable added: $BUFFER. This variable contains the output collected so far since the beginning of the script or the last <FLUSH>. It can also be manipulated, e.g. with $BUFFER =~ s/// which allows another layer of post-processing output.

Any ``print'' statements are now automatically converted to Print, so that we always have control over the output.

Now uses the new Liz::SetFields method in subroutines File, Normal, Return, new and handler. This should reduce the memory footprint a bit.

Version 4.31, 2 April 1999

Whenever an error occurs in a ModPerl environment, an email will be sent to the ServerAdmin containing the error message, the part of the Perl code where it occurred, all variables in the script, all environment variables, whatever HTML was already sent (including any SQL errors) and the complete Perl code as an attached file.

Version 4.30, 29 March 1999

The normal benchmark info at the end of the HTML-stream now also includes the approximate number of TCP/IP packets sent for this request.

Version 4.29, 28 March 1999

Added support for output buffering in the ModPerl environment. Standard function Flush( ) and pseudo-html code <FLUSH> now allow control over when specific parts of the Liz::Perl output stream are sent to the browser. Good use of output buffering can result in significantly faster loading in browser.

Optimized various regular expressions and/or made them constant for the lifetime of the process.

Version 4.28, 26 March 1999

Fixed problem with automatic session cookies when a directory was requested or a sub-request was being done.

Version 4.27, 25 March 1999

Added support for automatic session cookies with AutomaticSessionCookie, which should be installed as a PerlHeaderParserHandler.

Version 4.26, 12 March 1999

Checked all m// and s/// operators in the source and added the ``o'' flag when appropriate. This should increase the speed of processing new HTML significantly.

Standard function Cookie now sends an error message in the HTML-stream if an attempt is made to set a cookie after the HTTP-header was already sent.

Version 4.25, 9 March 1999

New standard function Cookie added: set a cookie for the whole site or a part of it. Hash %cookiejar is now also set with the cookies that are associated with a page.

Version 4.24, 8 March 1999

New standard function Benchmark( $string ) added: return or output benchmark information since the previous invocation of this standard function or the beginning of execution. Also accessible as HTML code <BENCHMARK identifying string>. Only works within the ModPerl environment.

Added internal subroutine ``RBenchmarkLP'' to make the above all possible. This is now also used by the internal subroutine ``handler'' for displayin the final benchmark for the whole file.

Finally fixed problem with headers appearing seemingly out of nowhere when calling $lp->Execute within ModPerl environment.

Version 4.23, 24 January 1999

Removed recording and returning of list of included files. This is no longer necessary with the improved caching scheme.

Added support for caching of Perl-script output with the CacheDirectory class method. Adapted internal routine ModPerlCache and method Perl to complete cache support.

Version 4.22, 15 January 1999

Added support for extra HTML (usually Javascript> to <RADIO...> and <CHECK...> pseudo-HTML.

Version 4.21, 9 January 1999

The <BUTTON> pseudo-HTML code now also allows spaces in the name field, provided they are enclosed by quotes.

Version 4.20, 6 January 1999

Standard function FrozenContent( $lastchanged ) now also returns the unix-time that was sent to the browser.

Version 4.19, 29 December 1998

Method Execute now removes the script itself from the error output when an error has occurred because of a croak().

Version 4.18, 28 December 1998

Made internal subroutine AsIs use the IO::File package with a local filehandle to be sure we don't have any interference with other global filehandles.

Moved subroutine GetImageDimensions to the Liz::Calc module. For now, Liz::Perl::GetImageDimensions will continue to work but should not beused in new code anymore.

Version 4.17, 27 November 1998

The environment variable $ENV{'LIZ_PERL'} is now being set with the Liz::Perl version that is active.

The ModPerl handler now looks for Squid compatible ``real'' IP number information and stores that in $ENV{'REMOTE_ADDR'}.

Version 4.16, 25 November 1998

The ModPerl handler now also outputs the name of the server along with the timing information when applicable.

Version 4.15, 9 November 1998

Fixed problem in Location so that everything keeps working if there is no $ENV{'SCRIPT_URI'}.

Version 4.14, 8 November 1998

Dummy HTML codes <CHECK..> and <RADIO..> now allow variable variable names to be specified.

Version 4.13, 14 October 1998

Multiple entries in a pulldown are now also handled correctly because the array in the caller's namespace is also checked, rather than just the variable.

Version 4.12, 9 October 1998

Added support for extra HTML with the PULLDOWN dummy HTML code. Adapted use and function of SelectLP accordingly.

Reduced memory footprint by using only fully qualified global variables and external subroutines.

Version 4.11, 11 September 1998

Fixed problem with Header(): now works properly in ModPerl environment. Also added documentation for the Header function.

Changed ContentType( $MIMEtype,$filename ) so that content disposition is sent if specified.

Fixed problem with AsIs in ModPerl environment if no <HTTP_HEADER> was given.

Version 4.10, 3 September 1998

Method new now removes Carriage Returns from any template that is specified by its contents. Templates specified by filename are considered to be Carriage Return clean and will therefore not be scanned for Carriage Returns.

Version 4.09, 14 August 1998

When an error occurs in ModPerl mode, only 10 lines of error are displayed around the error found, but only if the error occurred in the script itself. If the error occurred in a library, only the error message will be displayed.

Version 4.08, 2 August 1998

Standard function HTML( $filename ) now also accepts a HTML-stream as input.

Version 4.07, 30 July 1998

Standard <SUBMIT> buttons now use the variable name ``submit'' so that the variable $submit will be set with the string that was displayed in the button, this allowing multiple submit buttons to be used and still be able to distinguish which one was selected.

Version 4.06, 26 July 1998

New standard function Warn( $message ) added: send a warning that will be put in the data-stream when the first Print is executed. Also sets the global variable $Liz::Perl::WARN with a reference to the current WARN routine. This can be used by other modules to output error messages without interfering with headers etc.

Now sets the global variable $Liz::Perl::PRINT with a reference to the current Print routine (the alternative ``print'') currently in use.

Version 4.05, 25 July 1998

New standard function HTMLEncode( $string ) added: convert extended ASCII characters to HTML entities.

Version 4.04, 23 July 1998

Standard function FrozenContent( $lastchanged ) now also accepts relative times.

Version 4.03, 22 July 1998

New standard function ContentLength( $length ) added: allows specification of number of bytes that will be sent to the browser.

Version 4.02, 19 July 1998

New standard function Stop( ) added and associated <STOP> HTML code created. Stops whatever is happening.

Version 4.01, 18 July 1998

New standard function LastModified( $filename1,$filename2...) added: handy in conjunction with FrozenContent.

Version 4.0, 17 July 1998

Support for standard function FrozenContent( $lastchanged ) and HTML code <FROZENCONTENT> added. This now makes Liz::Perl a fully compliant ``If-Modified-Since'' / Status 304 (Not Modified) aware file handler in a ModPerl environment. Main advantage is that documents that are essentially fixed will be re-displayed from the local browser cache when possible.

Version 3.7, 16 July 1998

Support for standard function Aborted( ) added: returns true if the browser has broken the connection.

Version 3.6, 15 July 1998

Now aborts the script in Server Push if the connection to the client is lost. This should stop a lot of rogue server push scripts.

Now does not send timing information when ServerPush is active or the content type is changed to something other than text.

Support for standard function AsIs( $filename ) added: this sends a file directly to the browser when in ModPerl mode without using up any memory in Perl. This can be very useful when passing through large files in secure or server push situations. In all other modes it merely inserts the contents of the specified file.

Support for Content-Disposition added to standard functions ServerPush() and ContentType().

Standard function ``RGB2Hex'' added: convert from RGB values to hex colour code.

Version 3.5, 14 July 1998

Support for Server Push added. New standard routines are ServerPush and NextFrame. Changed numerous subroutines to add support.

Version 3.41, 13 July 1998

Any document that is accessed through the subroutine HTML( $filename ) is now also cached when used inside of ModPerl. New internal subroutine ModPerlCache takes care of that.

Standard function ``GET'' added: obtain the data from a URL into a variable.

Standard function ``Hex2RGB'' added: convert from hex colour code to RGB values.

Standard function ``URLDecode'' removed: is done automatically anyway and is not needed as a standard.

Version 3.4, 12 July 1998

User authentication can now be done within a Liz/ModPerl script: ModPerl Authentication handler Liz::Perl::Authenticate sets the environment variable $ENV{'REMOTE_USER_PASSWORD'}, which can be checked inside the Liz/ModPerl script. Should access be denied, either the HTML-code <ACCESS_DENIED> can be used, or the subroutine AccessDenied( $reason ) can be called.

Version 3.3, 9 July 1998

New subroutine HTML available when executing any code with Liz::Perl. It returns the HTML that was the result of executing the indicated template.

Fixed problem with headers being printed when doing a Redirect without a <HTTP_HEADER> code in the HTML. Any output printed before a HTTP_HEADER was encountered will now cause the header to be sent and any subsequent data to be part of the HTML stream. Any further HTTP_HEADER will then be ignored.

Version 3.25, 8 July 1998

Subroutines Scalars2Hash and Hash2Scalars of the module are now also available in any code executed with Liz::Perl.

Version 3.24, 7 July 1998

Methods File, Normal, Return and PHP now return the object itself so that they can be used more easily in one-liners.

Version 3.23, 4 July 1998

Subroutines Contents and WriteContents of the module are now also available within any code executed in Liz::Perl.

Version 3.22, 3 July 1998

Subroutines URLEncode and URLDecode of the module are now also available within any code executed in Liz::Perl.

Version 3.21, 30 June 1998

Routine HTML2Perl now makes sure that all tags are put between double quotes.

Version 3.2, 13 June 1998

Redirecting under ModPerl now properly exits the flow of the script and sends the appropriate headers. Changes to RRedirectLP, and handler. Global variable $REDIRECT introduced.

Method new now also allows ``//file'' notation to indicate the file to be activated.

Version 3.12, 11 June 1998

Now expands relative URLs to complete URL for REDIRECT HTML tag and Redirect() function.

Version 3.11, 10 June 1998

Now allow ``//file'' notation to indicate files relative to the document root of the web server.

Version 3.1, 27 May 1998

Method GET moved to the Liz::Calc module.

Version 3.0, 17 May 1998

Now inherits several methods from the Liz module. Methods removed from Liz::Perl are:

Version 2.21, 3 May 1998

<PULLDOWN> now allows extended format by specifying the word 'extended' as the first value parameter. Subroutine SelectLP was adapted to achieve this effect.

Version 2.2, 12 April 1998

Simple caching algorithm added: only checks mtime of main template.

Version 2.1, 10 April 1998

Support for <BUTTON> added. Document setting of $action when clicking on <BUTTON>.

Version 2.0, 1 March 1998

LizPerl The Next Generation. Main differences with previous versions are:

 - completely object oriented, a true Perl module
 - safe because execution takes place in a Safe sandbox
 - HTML can now be returned instead of printed
 - can be installed as a ModPerl handler
Version <2.0, December 1996 - February 1998

Unfortunately, no history was being kept here. Development started in December 1996 when I finally realised what you can do with -eval-.

Internally, the last version is known as 1.4beta for some reason.