MAN page from Old RedHat 6.X perl-HTML-EP-0.2010-6.i386.rpm
EP
Section: User Contributed Perl Documentation (1)
Updated: perl 5.005, patch 03
Index NAME
HTML::EP - a system for embedding Perl into HTML
SYNOPSIS
<html><head><title>CGI-Env</title></head> <ep-comment> This is an HTML document. You see. Perhaps you wonder about the unknown HTML tags like ep-comment above? They are part of the EP system. For example, this comment section will be removed and you won't see it in your browser. </ep-comment> <ep-perl> # This is an example of embedding Perl into the page. # We create a variable called time, containing the current # time. This variable will be used below. my $self = $_; $self->{'time'} = localtime(time()); ''; # Return an empty string; result becomes embedded into the # HTML page </ep-perl> <body><h1>The current time</h1> Your HTML::EP system is up and running: The current time is $time$. </body> </html> NEWS
HTML::EP does now have a homepage, a CVS repository and a bug trackingsystem. Try
http://html-ep.sourceforge.net/
DESCRIPTION
Have you ever written a CGI binary? Easy thing, isn't it? Was just fun!
Have you written two CGI binaries? Even easier, but not so much fun.
How about the third, fourth or fifth tool? Sometimes you notice thatyou are always doing the same:
- Reading and parsing variables
- Formatting output, in particular building tables
- Sending mail out from the page
- Building a database connection, passing CGI input to the database andvice versa
- Talking to HTML designers about realizing their wishes
You see, it's soon to become a pain. Of course there are little helpersaround, for example the CGI module, the mod_perl suite and lots of itmore. Using them make live a lot easier, but not so much as you like.the CGI(3) manpage. the mod_perl(3) manpage.
On the other hand, there are tools like PHP or WebHTML. Incrediblyeasy to use, but not as powerfull as Perl. Why not get the best fromboth worlds? This is what EP wants to give you, similar to ePerl orHTML::EmbPerl. I personally believe that EP is simpler and betterextendible than the latter two. the ePerl(1) manpage. the HTML::EmbPerl(3) manpage.
In short, it's a single, but extensible program, that scans an HTMLdocument for certain special HTML tags. These tags are replaced byappropriate output generated by the EP. What remains is passed to thebrowser. Its just like writing HTML for an enhanced browser!
Prerequisites
As far as I know
EP depends on no system dependent features. However,it relies on some other Perl modules:
- CGI
- The CGI module should be a part of your Perl core's installation. Ifnot, you should definitely upgrade to Perl 5.004. :-) My thanks toLincoln D. Stein <lsteinAATTgenome.wi.mit.edu>. Note, you need a lateversion, including the CGI::Cookie module.
- HTML::Parser
- This module is used for parsing the HTML templates. My thanks to GisleAas <aasAATTsn.no>.
- libwww
- The LWP library contains a lot of utility functions, for example HTMLand URL encoding and decoding. Again, my thanks to Gisle Aas <aasAATTsn.no>. :-)
- Mail::Internet
- Graham Barr <gbarrAATTpobox.com> wrote the MailTools package. Some partsof it, in particular the Mail::Internet module is used for sending mailfrom within the HTML page. Thank very much, Graham!
- Storable
- Raphael Manfredi's <Raphael_ManfrediAATTgrenoble.hp.com> excellent Storablemodule is used for storing sessions. I owe him much, as Storable isusefull in a lot of other modules.
Perl itself and the above modules are available from any CPAN mirror,for example
ftp://ftp.funet.fi/pub/languages/perl/CPAN/modules/by-module
Note that you don't need to install these manually, the
CPAN module willhelp you. See the the section on
Automatic Installation below.
Automatic Installation
Installing this module (and the prerequisites from above) is quite simple,if you have the
CPAN module available and network access, you mighttry an automatic installation:
perl -MCPAN -e shell
If the
CPAN prompt appears, asking you for commands, enter
install Bundle::HTML::EP
Manual Installation
If automatic installation doesn't work, you just fetch the archive, extractit with
gzip -cd HTML-EP-0.1125.tar.gz | tar xf -
(this is for Unix users, Windows users would prefer WinZip or somethingsimilar) and then enter the following:
cd HTML-EP-0.1125 perl Makefile.PL make make test
If any tests fail, let me know. Otherwise go on with
make install
This will put the required Perl modules into a destination wherePerl finds it by default. Additionally it will install a single
CGIbinary, called
ep.cgi.
The docs are available online with
perldoc HTML::EP
If you prefer an
HTML version of the docs, try
pod2html lib/HTML/EP.pm
in the source directory.
Using the CGI binary
You have different options for integrating
EP into your
WWW server,depending on which server you are using and the permissions you have.The simplest possibility is running an external
CGI binary. Anotheroption is to use mod_perl with Apache, see the section on
Using mod_perl below.
I suggest that you choose an extension and configure your WWW server forfeeding files with this extension into ep.cgi. For example, withApache, you can add the following lines to your srm.conf:
ScriptAlias /cgi-bin/ep.cgi /usr/bin/ep.cgi AddType x-ep-script .ep Action x-ep-script /cgi-bin/ep.cgi
This tells Apache that files with extension ep.cgi are handled by the
CGI binary
/usr/bin/ep.cgi. Make sure, that the ScriptAlias line isentered *before* any other ScriptAlias instruction! In particular,the following would be wrong:
ScriptAlias /cgi-bin/ /home/httpd/cgi-bin/ ... ScriptAlias /cgi-bin/ep.cgi /usr/bin/ep.cgi
The first rule would be applied before our rule, so that it couldnever match.
From now on your server will never return files with extension .epdirectly! Verify your installation by creating the following file:
<html><head><title>Local time</title></head> <body> The current time is: <ep-perl>scalar(localtime(time))</ep-perl> </body>
(Note that this is a much shorter version of the example in the synopsis.)Store it as
/test.ep on your web server and retrieve the file viayour Web server. If you see the time displayed, you are up and running.
Using mod_perl
The
EP package can be integrated into mod_perl, for example by usingthe following commands in
srm.conf:
PerlModule Apache::EP <Files *.ep> SetHandler perl-script PerlHandler Apache::EP->handler Options ExecCGI </Files>
Keep in mind, that mod_perl differs in many details from programming
CGIbinaries. In particular you might need to restart Apache for loadingchanges in modules.
Using the Internet Information Server
I am sure there is a better way of installation, in the sense of mod_perl,however, I am no
IIS expert. I can only recommend using Perl as an externalbinary, in the sense of
CGI.
The idea is to advice the IIS, that files with extension .ep have tobe executed by running
C:\Perl\bin\perl.exe c:\Perl\bin\ep.cgi %s%s
with
%s%s being the path to the
EP document. (Of course the paths have tobe adjusted to your local Perl.) This can be done by creating a newextension in the window ``Base directory/Configure''. (Window name translatedfrom the german
IIS, itīs ``Basisverzeichnis / Konfigurieren'' here and mightbe different in english.)
Available methods
All
EP tags are starting with the prefix
ep-. Some available tags are:
- ep-comment
- This is a multi-line tag for embedding comments into your HTML page. Butwhy use this tag, instead of the usual HTML comment, <!--? Thedifference is, that the user will never see the former.
Example:
<html> <!-- This is a comment. I like comments. --!> <ep-comment> This is another comment, but you won't see it in your browser. The HTML editor will show it to you, however! </ep-comment> </html>
Do not try to embed EP instructions into the comment section! Theywon't produce output, but they might be executed anyways.
- ep-perl
- This is for embedding Perl into your script. There are two versions ofit: A multiline version is for embedding the Perl code immediately intoyour script. Example:
<html> <head><title>The Date</title></head> <body> <h1>The Date</h1> <p>Hello, today its the</p> <p align=center> <ep-perl> # This little piece of Perl code will be executed # while scanning the page. # # Let's calculate the date! # my($sec,$min,$hour,$mday,$mon,$year) = localtime(time); # Leave a string with the date as result. Will be # inserted into the HTML stream: sprintf("%02d.%02d.%04d", $mday, $mon+1, $year+1900); </ep-perl> </p> </body> </html>If you don't like to embed Perl code, you may store it into a differentfile. That's what the single-line version of ep-perl is for: <html> <head><title>The Date</title></head> <body> <h1>The Date</h1> <p>Hello, today its the</p> <p align=center> <ep-perl src="date.pl"> </p> </body> </html>
You have noticed, that the little script's result was inserted into theHTML page, did you? It did return a date, in other words a string consistingof letters, digits and dots. There's no problem with inserting such a stringinto an HTML stream.But that's not always the case! Say you have a string like
Use </html> for terminating the HTML page.
This cannot be inserted as a raw string, for obvious reasons. Thus theep-perl command has an attribute output. Use it like this: <ep-perl output=html> 'Use </html> for terminating the HTML page.'; </ep-perl>
Possible values of the output attribute are raw (default), html(HTML encoded) and url (URL encoded).It's a common mistake, to use the Perl command return in embedded Perl.Never do that! If you need return (there are of course situations wherereturning can help), do it like this:
<ep-perl> sub eval_me { if ($this) { return 'foo'; } elsif ($that) { return 'bar'; } ''; } eval_me(); </ep-perl>See the section on Variables below for interactions between Perl variables andEP variables.For security reasons, you might set an attribute safe, as in
<ep-perl safe=1>...</ep-perl>
This will create a Safe compartment for you and run the embedded scriptin the compartment. Using this attribute is highly recommended!
- ep-mail
- This command will send an e-mail. The attributes will be used for creatingthe email header, in particular the subject, from and to attributeshould be used. Example:
<ep-mail subject="Howdy!" from="joeAATTispsoft.de" reply-to="joe@ispsoft.de" to="billAATTwhitehouse.gov"> Hello, Bill, old chap. How are you?
Yours sincerely, Jochen </ep-mail>
You can still use EP variables in the E-mail body, for example thefollowing works: <ep-mail subject="Test" reply-to="$cgi->email$" to="joeAATTispsoft.de" from="webmasterAATTwww.mydomain.com"> Hello, Joe, this e-mail was sent to you by $@cgi->name$. </ep-mail>
But note that we suppress conversion into HTML format in the mail body!See the section on Variables below for details.Recent sendmail versions are quite picky about validity of email addresses.Thus it is highly recommended that you use valid addresses for theto and from fields. If you want to customize the sender, you'dbetter choose a fixed from field and modify the reply-to fieldonly, as in the example above.
- ep-errhandler
- This command advices EP, what to do in case of errors. See the section on Error handlingbelow. Example:
<ep-comment> Set the template being used for system errors. </ep-comment> <ep-errhandler type=system src=/templates/syserr.html> <ep-comment> Likewise, set the template for user errors. </ep-comment> <ep-errhandler type=user src=/templates/usererr.html>
If an error occurs, the given scripts are loaded and used as templatesinstead of the current one. You don't need external files! Insteadyou can use <ep-errhandler type=user> <HTML><HEAD><TITLE>User error</TITLE></HEAD> <BODY><H1>User error</H1> <P>Replace user and continue. :-)</P> <P>To be serious, the following problem happened:</P> <PRE>$errmsg$</PRE> <P>Please return to the calling page, fix the problem and retry.</P> </BODY></HTML> </ep-errhandler>
However, you might prefer to use a single error template and of courseit's faster to use external error templates than parsing builtintemplates. (At least, if no error occurs. :-)
- ep-error
- This command forces an error message. See the section on Error handling below.You can trigger user or system errors by setting the type attributeto the values system (default) or user. The msg attribute isfor setting the error message.
Example:
<ep-comment> If no email address was entered, force a user error. </ep-comment> <ep-if eval="$cgi->email$"> Email address is ok. <ep-else> <ep-error msg="Missing email address" type=user> </ep-if>
- ep-database
- This command connects to a database. Its attributes are dsn, userand password corresponding to the same attributes of the DBI connectmethod. See the DBI(3) manpage for details on DBI.
Example:
<ep-database dsn="DBI:mysql:test" user="joe" password="Authorized?Me?">
You can use different database connections by using the dbh attribute: <ep-database dbh="dbh2" dsn="DBI:mSQL:test">
The dbh attribute advices EP to store the DBI handle in the givenvariable. (Default: dbh) See the section on Variables below.
- ep-query
- This command executes an SQL statement. The query attribute willbe used for passing the SQL statement. Of course a multiline versionis available, thus
<ep-query statement="INSERT INTO foo VALUES (1, 'bar')">
is the same as <ep-query> INSERT INTO foo VALUES (1, 'bar') </ep-query>
If your query retrieves a result, use the result attribute to store itin a variable, for example like this: <ep-query statement="SELECT * FROM employees" result="employees" resulttype="hash" startat=0 limit=-1>
This will create a variable employees, an array ref of hash refs.You can use the ep-list command for displaying the output. Seethe section on Variables below.When using multiple database connections, use the dbh attribute forchoosing the connection. (See the ep-database method above.)
If you have big result tables, you might prefer DBI's fetchrow_arrayrefmethod over creating hash refs, because arrays are created faster thanhash refs. This is achieved by setting the attribute resulttype toarray. The default is hash. Other resulttypes are single_hashand single_array: If your query will return at most a single element,then the result variable will contain the first row (or an undefinedvalue) and not an array.
Sometimes you don't want to retrieve the complete result table. In thatcase you can use the attributes startat and limit. For example,to retrieve rows 0-19, use startat=0 and limit=20. Likewise youwould use startat=20 and limit=20 for rows 20-39.
When using the MySQL engine, the startat and limit attributesare directly mapped to MySQL's LIMIT clause.
- ep-list
- This command is used to display an array of refs. Lets assume, thatthe variable employees contains a an array ref of refs with the attributesname and department. Then you could create a table of employees asfollows:
<table><tr><th>Nr.</th><th>Name</th><th>Department</th> <ep-list items="employees" item="e"> <tr><td>$i$</td><td>$e->name$</td><td>$e->department$</td> </ep-list> </table>
This will be processed as follows: For any item in the array,retrieved from the variable employees, create a variable e anddisplay the text between ep-list and /ep-list for it by replacingthe patterns $e->name$ and $e->department$ with the correspondingvalues.The variable i is initially set to 0 and incremented by onewith any element.
As an alternative to the items attribute, you may prefer therange attribute: For example
<ep-list range="1..12" item=month><OPTION>$month$</ep-list>
will create the options array of a select box for you, where theuser can select a month. If your prefer month names, you may betterchoose <ep-list range="jan,feb,mar,apr,jun,jul,aug,sep,oct,nov,dec" item=month><OPTION>$month$</ep-list>
It is even possible to mix both versions, as in <ep-list range="1..3,6..7,10" item=m><OPTION>$m$</ep-list>
See the ep-select command below for another example of therange attribute.It is possible to nest multiple ep-list statements, as in
<ep-list range="1..3" item="i"><ep-list range="4..6" item="j">$i$$j$ </ep-list></ep-list>
This will create the output ``14 15 16 24 25 26 34 35 36''.
- ep-select
- This is similar to ep-list, but it is specifically designed for creatingSELECT boxes and similar things. We explain it by example:
<ep-select name="year" range="1991..1995" item="y" selected="$cgi->year$"> <OPTION $selected$>$y$</ep-select>
If you supply a selected attribute, then a variable selected willbe created for any item. The value will be either an empty string orthe word SELECTED (configurable via the attribute selected-text),depending on whether the item matches the selected value or not.
- ep-input
- This is usefull for reading an objects data out of CGI variables.Say you have a form with input fields describing an address, thefield names being address_t_name, address_t_street, address_n_zip andaddress_t_city. By using the command
<ep-input prefix="address_" dest="address">
the EP program will create a variable ``address'' for you which is anhash ref as follows: $cgi = $_->{cgi}; $_->{address} = { name => { col => 'name', val => $cgi->param("address_name"), type => 't', }, street => { col => 'street', val => $cgi->param("address_street"), type => 't', }, zip => { col => 'zip', val => $cgi->param("address_zip"), type => 'n', }, city => { col => 'city', val => $cgi->param("address_city"), type => 't' } };In general column names beginning with address will be splitted intoprefix_type_suffix, the type being one of
- t
- Text columns (CHAR, VARCHAR, BINARY, or whatever), that will be quotedusing the $self->{'dbh'}->quote() method.
- n
- Numeric columns (INTEGER, REAL, ...) that will be left untouched
- dd
- dm
- dy
- Day, month and year of a date. The combined fields will be quoted as'yyyy-mm-dd'.
- s
- Set columns as created using MultiSelect boxes; the selected valueswill be used for creating a comma separated string.
The idea is generating SQL queries automatically out of theaddress variable. This task is supported by the sqlquery attribute:
<ep-database dsn="DBI:mysql:test"> <ep-input prefix="address_" dest="a" sqlquery=1> <ep-comment>Create a new record, if no ID is given</ep-comment> <ep-if eval="$cgi->id$"> <ep-query statement="INSERT INTO addresses ($@a->names$) VALUES ($@a->values$)"> <ep-else> <ep-query statement="UPDATE addresses SET $@a->update$ WHERE id = $@id$">
The sqlquery creates attributes names, values and update foryou, that may be used in INSERT or UPDATE queries. Note that the ep-inputmust be preceeded by an ep-database call, because it is using DBI'squote method. the DBI(3) manpage.There are situations where you want to fetch not only a single object,but a list of objects. Suggest an order form of articles. Then youmight have input fields art_0_t_name, art_0_n_count, art_0_n_price,art_1_t_name, ...
In that case you can give the ep-input command an attribute list, likethis:
<ep-input prefix="art_" dest="art" list=1>
The module will read an array ref of objects to the variable dest.Any object will have an additional scalar variable i referring tothe items number, beginning with 0. In other words, you can process theorder form as follows: <ep-input prefix="art_" dest="art" list=1> <ep-perl> my $self = $_; my $sum = 0.0; for (my $i = 0; defined($self->{cgi}->param("art_$i_n_count")); $i++) { $sum += $self->{cgi}->param("art_$i_n_count") * $self->{cgi}->param("art_$i_n_price") } '' </ep-perl> <ep-mail from="$cgi->email$" to="orderAATTmydomain" subject="Order form"> The following items have been ordered: Nr. Price Article
<ep-list> $art->count->val$ $art->price->val$ $art->name->val$ </ep-list>
Total sum: $sum$ </ep-mail>
- ep-input-sql-query
<ep-input-sql-query dest=art>
This method is internally called by ep-input and implements thecreation of the names, values and updates attributes.It takes as input the hash ref given by the variable dest,usually created by ep-input. The hash ref consists of columnnames as keys and hash refs with the attributes type andval.
The main reason for putting this into a separate method issubclassing: It is quite usual, that you want ep-input to readthe data, then do some verification and/or modification on thedata (for example, canonicalizing dates) and finally createthe SQL query. This can be done quite easily by subclassingthe _ep_input_sql_query method: Within the method youverify and/or modify data entered by the user and then callthe super class.
For example, a typical subclass implementation could look likethis:
sub _ep_input_sql_query { my $self = shift; my $attr = shift; # If the user left the MYCOL column empty, set it to NULL. my $dest = $attr->{'dest'}; $self->{$dest}->{'MYCOL'} = undef if $self->{$dest}->{'MYCOL'} eq ''; $self->SUPER::_ep_input_sql_query($attr); }
- ep-include
- Sometimes you want to source external files. This can be doneby using
<ep-include file="myfile">
If a file with the given name doesn't exist, the file name is treated asbeing relative to your WWW servers DOCUMENT_ROOT directory.
- ep-exit
- This directive terminates processing of the current HTML page.
- ep-set
- This instruction is setting an EP variable. Suggest the followingexample:
<ep-set var=myvar val=value>
From now on you can use $myvar$
as an alias for ``value''. There's also a multiline version: <ep-set var=myvar>value</ep-set>
The main difference between the single and the multiline version is thatthe multiline version allows supressing variable interpretation by settingthe noparse attribute: <ep-set var=myvar noparse=1>my $value$</ep-set>
The above example is indeed setting myvar to ``my $value$'' *without*escaping $value$!
Conditional HTML
It is possible to blank out parts of the
HTML document. See the followingexample:
<html><head><title>Conditional HTML</title></head> <body> <h1>Conditional HTML</h1> <ep-if eval="$_->{cgi}->param('i') < 0"> You have entered a negative number for i! <ep-else eval="$_->{cgi}->param('i') == 0"> You have entered zero for i! <ep-else> <ep-if eval="$_->{cgi}->param('j') < 0"> You have entered a negative number for j! <ep-else eval="$_->{cgi}->param('h') == 0"> You have entered zero for j! <ep-else> Ok, both numbers are positive. </ep-else> </ep-else> </body> </html>The example is of course somewhat unnatural, because you'd better usea single ep-perl in that case, but it shows that we can usearbitrary complex structures of conditional
HTML.
The eval attribute is simply treated as a truth value, as in Perl.Thus empty strings or numeric zeros are FALSE, everything else is TRUE.This is reversed, if you replace eval with neval:
<ep-if neval="$a$"> a is not set <ep-else> a is set </ep-if>
If you'd like to compare numeric values, use the
cnd attribute, as in
<ep-if cnd="$a$<$b$"> a is lower than b <ep-else> a is greater than or equal to b </ep-if>
You may choose either of ==, !=, <, >, <= or >= for the condition. Andfinally you may compare string values like this:
<ep-if cnd="'$a$' eq '$b$'"> a is equal to b </ep-if>
Note the use of the single quotes, which is really required here.Available conditions are eq and ne.
As with ep-list, you may nest multiple ep-if's or combine them withep-list. The following is invalid, though:
<ep-list range="1..3" item="i"> <ep-if cnd="$i$<3">ok</ep-list></ep-if>
As the ep-if starts within the ep-list, it must also be terminatedbefore the corresponding /ep-list.
Localization
Localization is available via the
HTML::EP::Locale module. Currentlyit only offers methods for localizing strings.
To access the module, let's assume you prefer your visitors readingthe german (de) version of your page, but it is also available inenglish (en). Then start your HTML page with
<ep-package name="HTML::EP::Locale" accept-language="de,en">
When the package is loaded, it tries to guess your documents language.The default language is
de (german) or whatever you choose wheninstalling the package. Another language can be specified by
- *
- By setting the CGI variable language, for example by makinga link to mypage.ep?language=en.
- *
- By setting the environment variable HTTP_ACCEPT_LANGUAGE; mostbrowsers do this for you. For example with Netscape, this variableis configurable via Edit/Preferences/Navigator/Languages.
Two possibilities are available for localizing strings. For short stringslike titles, headers or Link refs you might prefer this version:
<ep-language de="Titel" en="Title">
Obviously this is not appropriate for longer strings and it must notcontain
HTML patterns. Thus another version is available:
<ep-language language=de> <p>Dies ist ein Absatz.</p> <p>Dies ist der zweite Absatz.</p> <ep-language language=en> <p>This is one paragraph.</p> <p>This is another paragraph.</p> </ep-language>
Note you need not use a /ep-language for terminating the germanpart, similar to the ep-if, ep-elseif, ..., ep-else, /ep-ifstructure.
A special problem with localization is the choice of a characterset. You can fix a certain character set with something like
<META HTTP-EQUIV="Content-type" CONTENT="text/html; CHARSET: iso-8859-2">
Error handling
Error handling with
EP is quite simple: All you do in case of errors isthrowing a Perl exception. For example,
DBI handles are created withthe RaiseError attribute set to 1, so that
SQL errors trigger a Perlexception. You never care for errors!
However, what happens in case of errors? In that case, EP will use thetemplate that you have set with ep-errhandler and treat it like anordinary EP document, by setting the variables errmsg and admin.
If you don't set an error handler, the following template will be used,which is well suited for creating an own error template:
<html><head><title>Internal error</title></head> <body><h1>Internal error</h1> <p>An internal error occurred. The server has not been able to fullfill your request. The error message is:</p> <pre> $errmsg$ </pre> <p>Please contact the Webmaster, <a href="mailto:$admin$">$admin$</a>, tell him the URL, the time and error message. </p> <p>We apologize for any inconvenience, please try again later!</p> <br><br><br><p>Yours sincerely,</p><p>The Webmaster</p> </body> </html>
Variables
It is important to understand, how
EP variables work, in particular whenworking with ep-perl.
You always have an object $_, which is an instance of the HTML::EPclass (a subclass of HTML::Parser). This object has certain attributes,in particular $_->{cgi}, a CGI object and $_->{dbh}, the DBIhandle. (Of course valid after ep-database only.) If you want to setor modify a variable, you have to set $_->{varname}. If you want toretrieve the value, use the same. Note that you cannot use $_ fora long time, as it will be changed by Perl loops and the like, thusyour Perl code typically starts with
$_ = $self;
But how do you access the variable from within
EP documents? You justwrite
$varname$
This will be replaced automatically by the parser with the value of
$_->{varname}. Even more, the value will be convertedinto
HTML source!
If varname is a structured variable, for example a hash or array ref,you may as well use
$varname->attrname$or
$varname->0$
to access
$_->{varname}->{attrname} or
$_->{varname}->[0], respectively. A specialvalue of
varname is
cgi: This will access the
CGI variable ofthe same name, thus the following are equivalent:
$cgi->email$
and
$_->{cgi}->param('email');But what, if you don't want your variable to be
HTML encoded? Youmay as well use
$@varname$ (Raw) $#varname$ (URL encoded) $~varname$ (SQL encoded)
The latter uses the
$_->{dbh}->
quote() method. In particular thisimplies that you have to be connected to a database, before usingthis tag!
You can even use these symbols in attributes of EP commands. Forexample, the following will be usefull when sending a mail:
<ep-mail subject="Howdy!" from="$@cgi->email$" to="billAATTwhitehouse.gov">
Attributes may include
EP variables, just like ordinary
HTML code.Even more, they may contain Perl code which is evaluated just likecode between
<ep-perl> and
</ep-perl>. However,you need to use the variable
$_ in the code, because the packageotherwise doesn't detect what you want it to do.
See the section on Custom variable formatting for setting up your own formats.
Of course you can set EP variables from within an ep-perl section. Butsometimes it is desirable to set them from within HTML. In such casesyou can do something like
<ep-set var="a" val="b">
Now, if you do a
Variable a has the value $a$.
the value
b will be emitted. It is also possible to set multilinevariables:
<ep-set var="a"> This is a template, extending a single line. </ep-set>
Custom variable formatting
Sometimes the builtin formatting methods of
HTML::EP are not sufficient.A good example are currencies. These can be handled with format methods.For example, see the following method for german currency values:
<ep-package name="MyPackage"> <ep-perl> package MyPackage; sub _format_DM { my($self, $val) = @_; sprintf("%.2f DM", $val); $val =~ s/\./,/; $val; }; '' </ep-perl>This can be used as follows, suggest we have the following variables:
a = 1 b = 2.4 c = 34.47
then we can use
a = $&DM->a$ => 1,00 DM b = $&DM->b$ => 2,40 DM c = $&DM->c$ => 34,47 DM
In other words: Use the special marker
&, followed by the customformats method name, the dereferencing operator and finally the variablename.
The above method is already predefined by the HTML::EP::Locale module.
As you have seen, the pattern $&METHODNAME->var$ triggers the callof
$self->_format_METHODNAME($self->{'var'});It is not always usefull to fix a method name. In such cases you mayinstead store a code ref in
Modifying the CGI headers
The attribute
$self->{'_ep_heaaders'} is containing arguments that youwant to pass to
CGI->
header(). Use it like this:
<ep-perl> $_->{'_ep_headers'} = { '-status' => '402 Payment required', '-expires' => '+3d' } </ep-perl> Doing a redirect
A redirect is moving the browser to another page without actuallydisplaying the current page. You can do it like this:
<ep-redirect target="http://other.server/other/page">
Producing Non-HTML
Say you want a
CGI binary that creates a gif and not an
HTML document.(See the
ifgif.ep file from the
SNMP::Monitor distribution for anexample.) Two problems are arising here: First of all you have tocreate your own headers. Next you *must* prevent that
EP is emittingany output, because this might trash your images validity. Here'swhat to do:
<ep-perl> my $self = $_; my $cgi = $self->{'cgi'}; $self->_ep_database({'dsn' => 'DBI:mysql:test', 'user' => 'joe', 'password' => 'joe'}); $self->_ep_query({'statement' => "SELECT image FROM images WHERE" . " id = " . $cgi->param('id'), 'result' => 'im', 'resultype' => 'single_hash'}); $self->print($cgi->header('-type' => 'image/gif'), $self->{im}->{'image'}); $self->Stop(); </ep-perl>Note the use of
$self->
Stop()!
NPH Scripts
The Apache server and other
WWW servers have a nice feature that allowsyou to return
HTML pages line by line: If your script is called something likenph-myscript then the server is passing the scripts output to the browserimmediately. This is usefull, for example, if you display the output ofa traceroute command: You'd like to see any line immediately, but it may takesome time untill the next line arrives.
Unfortunately NPH scripts are not well suited for HTML::EP: One of EP'smajor targets is that you need not care for errors: They may occur atany point but are still catched and handled by creating an error message.However, there's no other way to guarantee this without bufferingoutput until the script ends.
If you really need to use NPH, do it like this:
<ep-perl> my $self = $_; local $| = 1; # make sure that Perl isn't buffering $self->print($self->{'cgi'}->header('-type' => 'text/html', '-nph' => 1)); for (my $i = 0; $i < 20; $i++) { $self->print("This is line $i. Waiting one second ...\n") sleep 1; } $self->Stop(); </ep-perl>Note, that *no* more output will be produced by
EP after calling
$self->
Stop()!
DEBUGGING
Debugging CGI applications is always a problem. The EP module does itsbest to support you.
Whenever you supply a CGI variable debug, then the module will enterdebugging mode. For example if your document is /mypage.ep, thentell your browser to fetch /mypage.ep?debug=1. You won't see theusual HTML page, but a plain text page with lots of debugging messagesand the created HTML source.
You may extend the debugging code with sequences like
<ep-perl> my $self = $_; $self->print("I'm here!\n") if $self->{debug}; </ep-perl>Note that you should not call the
print function directly, but the
print method! The former works well in CGI environments, but EPshould work even in other environments as well.
But sometimes this is not sufficient: What's inserting debuggingmessages compared to using the Perl debugger? In that case youcan emulate a CGI environment as follows:
export DOCUMENT_ROOT=/usr/local/www/htdocs export PATH_TRANSLATED=$DOCUMENT_ROOT/mypage.ep export REQUEST_METHOD=GET export QUERY_STRING="var1=val1&var2=val2" perl -d /usr/bin/ep.cgi
This allows you single-stepping through your program, displaying variablevalues and the like.
However, the debug variable is obviously a security problem. For thatreason the debughosts variable is present in HTML::EP::Config: Youshould set it to a regular expression matching the IP numbers of hoststhat are allowed to enable debugging mode. The Makefile.PL should queryfor appropriate settings automatically while running.
EXAMPLES
The program comes with a set of examples incorporated. These are:
- A simple Unix user administration in examples/admin.
- A generic frontend for editing DBI tables in examples/edit.ep
- A POP3 client for the web in examples/pop3.
Other examples are:
- The SNMP monitor, a utility for watching, logging and displaying interface utilization and status of network interfaces via WWW. See the directory authors/id/JWIED on any CPAN mirror, for example ftp://ftp.funet.fi/pub/languages/perl/CPAN.
- The EP Explorer, an application I wrote for managing printer queues on a Unix hosts. The user can select a file for printing it, much like he did within the Windows explorer. Likewise, he can watch the printer status.
- The HTML::EP::Glimpse package, a simple search engine based on Glimpse. (In other words, some flavour of WebGlimpse, which is much simpler to install and maintain and allows a free design.)
EXTENSIONS
It is quite easy to write own methods.
Single line extensions
For example, suggest you want a method for setting
EP variables:
<ep-set var="e" value=1>
Once the variable is created, you can access it via
$e$
This can be done like this:
<ep-perl package="HTML::EP"> # Write a handler for ep-env: sub _ep_set ($$) { my($self, $attr) = @_; my $var = $attr->{'var'}; my $val = $attr->{'value'}; $self->{$var} = $val; ''; } # Return an empty string: ''; </ep-perl>
Note that we used the name
_ep_set: By default the
EP module takesthe method name (
ep-env in out case) translates all hyphens tounderscores and adds a leading underscore. We'll see in the nextsection how you can override this behaviour.
Multi line extensions
But how to write methods, that use a
<tag> ..
</tag>syntax? As an example, we write a method for creating external files.The method receives two attributes, a
file attribute for the filesname and a
contents attribute for the files contents. The methodcan be used in two ways:
<ep-file file="test.dat" contents="Hi!">
or like this, in multiline mode:
<ep-file file="test.dat"> Hi! </ep-file>
Here it is:
<ep-perl package="HTML::EP"> # Write a handler for ep-file: sub _ep_file { my $self = shift; my $attr = shift; my $contents = $self->AttrVal($attr->{'contents'}, @_); my $file = $attr->{'file'}; require Symbol; my $fh = Symbol::gensym(); (open($fh, ">$file) && (print $fh $contents) && close($fh)) or die "Error while creating $file: $!"; ''; } # Return an empty string: ''; </ep-perl>The main difference to the previous example is that our method isthat a special attribute (
contents) is defined, that may bepassed as part of the ep-file statement. However, if you don'tdefine it as part of the statement, the
AttrVal method readsmore text from the document untill it finds a matching /ep-file.
Note the use of the Symbol package when accessing files: *Never* useglobal handles like
open(FILE, ...)
as this might break future multithreading code!
The above example works well, if you don't need to nest yourstatement. If this should be the case, you need to deal withEP's token streams. See the ep-if and ep-list methods forexamples.
External extensions
So far we have discussed only minor extensions that we did install aspart of
HTML::EP. However, this is somewhat dangerous with mod_perl:Suggest you have multiple virtual hosts. It might happen, that virtualhost
www.foo.com defines a method ep-file, but
www.bar.net definesanother. We'd have an immediate name space clash.
To prevent such a namespace pollution, EP supports external extensionswith an inheritage model that is borrowed from Perl. Suggest we writea Shop extension. Of course this extension borrows from HTML::EP::Session.Thus we have the following class design:
Shop ---isa---> HTML::EP::Session ---isa---> HTML::EP
We start writing our Shop extension like any other Perl package:
package Shop; @Shop::ISA = qw(HTML::EP::Session); # HTML::EP::Session inherits # from HTML::EP
sub _ep_shop_session { my($self, $attr) = @_; # Initialize the session ... ''; } sub init { my $self = shift; if (!$self->{'_ep_shop_initialized'}) { $self->{'_ep_shop_initialized'} = 1; $self->SUPER::init(); # Do something here ... } }In the
HTML page we load this package as follows:
<ep-package name="Shop"> <ep-shop-session>
This will do a
require Shop, bless the object
$self into theclass
Shop and call
$self-init()>. Note that we allow the initmethod to be called more than once, this is important for stackingpackages.
By default packages are loaded from Perl's system directories. Youcan use the attribute lib to add private directories to the librarysearch path. This can be relative to the servers document root, as in
<ep-package name="Shop" lib="/perl-lib">
Inheriting from multiple extensions
You may use multiple ep-package statements, as in
<ep-package name="HTML::EP::Locale"> <ep-package name="HTML::EP::Session">
Your object will be blessed into a new class, that inherits fromboth. However, note that the order is reversed: In the aboveexample, your object will be an instance of class
HTML::EP::PACK2and
HTML::EP::PACK2::ISA will be set to
qw(HTML::EP::Session HTML::EP::Locale)
CHANGES
This section describes user visible changes against previous versions.For details and other modifications see the
ChangeLog file, that ispart of the distribution.
- epparse
- epperl
- In previous versions it was not possible to include EP variables orPerl code in attributes of EP commands, unless using a prefixepparse- or epperl-, as in
<ep-mail to=joe epparse-from="$cgi->mail$" subject=Hello>
This is no longer the case, because the package now autodetects whetheryou are using such constructs. (At least it should. :-) The obviousdisadvantage is an incompatibility, but the new version is much betterreadable and surprisingly even (much!) faster, because only hash valuesare modified and not hash structures.
TODO
- Create an EP server that is accessible via a small C wrapper
- Add a preprocessor, that creates Perl code as output.
AUTHOR AND COPYRIGHT
This module is
Copyright (C) 1998-1999 Jochen Wiedmann Am Eisteich 9 72555 Metzingen Germany
Phone: +49 7123 14887 Email: joeAATTispsoft.de
All rights reserved.
You may distribute this module under the terms of eitherthe GNU General Public License or the Artistic License, asspecified in the Perl README file.
SEE ALSO
the
DBI(3) manpage, the
CGI(3) manpage, the
HTML::Parser(3) manpage
Index
- NAME
- SYNOPSIS
- NEWS
- DESCRIPTION
- Prerequisites
- Automatic Installation
- Manual Installation
- Using the CGI binary
- Using mod_perl
- Using the Internet Information Server
- Available methods
- Conditional HTML
- Localization
- Error handling
- Variables
- Custom variable formatting
- Modifying the CGI headers
- Doing a redirect
- Producing Non-HTML
- NPH Scripts
- DEBUGGING
- EXAMPLES
- EXTENSIONS
- Single line extensions
- Multi line extensions
- External extensions
- Inheriting from multiple extensions
- CHANGES
- TODO
- AUTHOR AND COPYRIGHT
- SEE ALSO
This document was created byman2html,using the manual pages.