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>

WARNING
    THIS IS ALPHA SOFTWARE. It is *only* 'Alpha' because the interface (API)
    is not finalised. The Alpha status does not reflect code quality or
    stability.

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 that you
    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 and
        vice versa

        Talking to HTML designers about realizing their wishes

    You see, it's soon to become a pain. Of course there are little helpers
    around, for example the CGI module, the mod_perl suite and lots of it
    more. 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/FI or WebHTML. Incredibly
    easy to use, but not as powerfull as Perl. Why not get the best from
    both worlds? This is what EP wants to give you, similar to ePerl or
    HTML::EmbPerl. I personally believe that EP is simpler and better
    extendible 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 HTML
    document for certain special HTML tags. These tags are replaced by
    appropriate output generated by the EP. What remains is passed to the
    browser. 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. If not, you should definitely upgrade to Perl
                5.004. :-) My thanks to Lincoln D. Stein
                <lstein@genome.wi.mit.edu>. Note, you need a late version,
                including the CGI::Cookie module.

    HTML::Parser
                This module is used for parsing the HTML templates. My
                thanks to Gisle Aas <aas@sn.no>.

    libwww      The LWP library contains a lot of utility functions, for example
                HTML and URL encoding and decoding. Again, my thanks to
                Gisle Aas <aas@sn.no>. :-)

    Mail::Internet
                Graham Barr <gbarr@pobox.com> wrote the MailTools package.
                Some parts of it, in particular the Mail::Internet module is
                used for sending mail from within the HTML page. Thank very
                much, Graham!

    Storable    Raphael Manfredi's <Raphael_Manfredi@grenoble.hp.com> excellent
                Storable module is used for storing sessions. I owe him
                much, as Storable is usefull in a lot of other modules.

    URI         You already know the name Gisle Aas <aas@sn.no>, don't you? :-)
                URI is yet another of its packages, we need the URI::Escape
                module.

    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 will
    help 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
    might try 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,
    extract it with

        gzip -cd HTML-EP-0.1125.tar.gz | tar xf -

    (this is for Unix users, Windows users would prefer WinZip or something
    similar) 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 where Perl
    finds it by default. Additionally it will install a single CGI binary,
    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. Another
    option 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 for
    feeding files with this extension into `ep.cgi'. For example, with
    Apache, you can add the following lines to your `srm.conf':

        ScriptAlias /cgi-bin/ep.cgi /usr/bin/ep.cgi
        AddHandler 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 is
    entered *before* any other ScriptAlias instruction!

    From now on your server will never return files with extension .ep
    directly! 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 via your Web server. If you see the time displayed, it are up and
    running.

  Using mod_perl

    The EP package can be integrated into mod_perl, for example by using the
    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 CGI
    binaries. In particular you might need to restart Apache for loading
    changes in modules.

  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.
        But why use this tag, instead of the usual HTML comment, `<!--'? The
        difference 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! They
        won't produce output, but they might be executed anyways.

    ep-perl
        This is for embedding Perl into your script. There are two versions
        of it: A multiline version is for embedding the Perl code
        immediately into your 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
        different file. 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
        the HTML page, did you? It did return a date, in other words a
        string consisting of letters, digits and dots. There's no problem
        with inserting such a string into 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
        the ep-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 where returning 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 and EP 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
        script in the compartment. Using this attribute is highly
        recommended!

    ep-mail
        This command will send an e-mail. The attributes will be used for
        creating the email header, in particular the `subject', `from' and
        `to' attribute should be used. Example:

            <ep-mail subject="Howdy!" from="joe@ispsoft.de"
                     reply-to="joe@ispsoft.de" to="bill@whitehouse.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 the
        following works:

            <ep-mail subject="Test" reply-to="$cgi->email$" to="joe@ispsoft.de"
                     from="webmaster@www.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 the *to* and *from* fields. If you want to customize
        the sender, you'd better choose a fixed *from* field and modify the
        *reply-to* field only, as in the example above.

    ep-errhandler
        This command advices EP, what to do in case of errors. See the
        section on "Error handling" below. 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
        templates instead of the current one. You don't need external files!
        Instead you 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
        course it's faster to use external error templates than parsing
        builtin templates. (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* attribute to the values `system' (default) or `user'. The
        *msg* attribute is for 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',
        `user' and `password' corresponding to the same attributes of the
        DBI connect method. 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 given
        variable. (Default: `dbh') See the section on "Variables" below.

    ep-query
        This command executes an SQL statement. The `query' attribute will
        be used for passing the SQL statement. Of course a multiline version
        is 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 it in 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. See the
        section on "Variables" below.

        When using multiple database connections, use the *dbh* attribute
        for choosing the connection. (See the *ep-database* method above.)

        If you have big result tables, you might prefer DBI's
        *fetchrow_arrayref* method over creating hash refs, because arrays
        are created faster than hash refs. This is achieved by setting the
        attribute *resulttype* to array. The default is hash. Other
        resulttypes are *single_hash* and *single_array*: If your query will
        return at most a single element, then the result variable will
        contain the first row (or an undefined value) and not an array.

        Sometimes you don't want to retrieve the complete result table. In
        that case you can use the attributes *startat* and *limit*. For
        example, to retrieve rows 0-19, use startat=0 and *limit=20*.
        Likewise you would use startat=20 and limit=20 for rows 20-39.

        When using the *MySQL* engine, the *startat* and *limit* attributes
        are directly mapped to MySQL's *LIMIT* clause.

    ep-list
        This command is used to display an array of refs. Lets assume, that
        the variable `employees' contains a an array ref of refs with the
        attributes *name* and *department*. Then you could create a table of
        employees as follows:

            <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' and
        display the text between ep-list and /ep-list for it by replacing
        the patterns $e->name$ and $e->department$ with the corresponding
        values.

        The variable *i* is initially set to 0 and incremented by one with
        any element.

        You must not create a variable for the *items* attribute: When using
        a *range* attribute instead of *items* then a variable list will be
        created for you. The *range* attribute can be either `start..stop'
        in which case a list of the numbers start..stop will be created.
        Otherwise the attribute must be a comma separated list of values.
        See the *ep-select* command below for an example of the *range*
        attribute.

    ep-select
        This is similar to ep-list, but it is specifically designed for
        creating SELECT 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*
        will be created for any item. The value will be either an empty
        string or the 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, the
        field names being address_t_name, address_t_street, address_n_zip
        and address_t_city. By using the command

            <ep-input prefix="address_" dest="address">

        the EP program will create a variable "address" for you which is an
        hash 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
        into `prefix_type_suffix', the type being one of

    t           Text columns (CHAR, VARCHAR, BINARY, or whatever), that will be
                quoted using 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
                values will be used for creating a comma separated string.

        The idea is generating SQL queries automatically out of the
        `address' 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* for
        you, that may be used in INSERT or UPDATE queries. Note that the
        *ep-input* must be preceeded by an *ep-database* call, because it is
        using DBI's *quote* 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 you might 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,
        like this:

            <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 to
        the items number, beginning with 0. In other words, you can process
        the order 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="order@mydomain"
                     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-include
        Sometimes you want to source external files. This can be done by
        using

            <ep-include file="myfile">

        If a file with the given name doesn't exist, the file name is
        treated as being relative to your WWW servers *DOCUMENT_ROOT*
        directory.

    ep-exit
        This directive terminates processing of the current HTML page.

  Conditional HTML

    It is possible to blank out parts of the HTML document. See the
    following example:

        <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 use a
    single ep-perl in that case, but it shows that we can use arbitrary
    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. And
    finally 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.

  Localization

    Localization is available via the HTML::EP::Locale module. Currently it
    only offers methods for localizing strings.

    To access the module, let's assume you prefer your visitors reading the
    german (de) version of your page, but it is also available in english
    (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 when
    installing the package. Another language can be specified by

    *       By setting the CGI variable *language*, for example by making a link
            to mypage.ep?language=en.

    *       By setting the environment variable *HTTP_ACCEPT_LANGUAGE*; most
            browsers do this for you. For example with Netscape, this
            variable is configurable via
            Edit/Preferences/Navigator/Languages.

    Two possibilities are available for localizing strings. For short
    strings like 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 not
    contain 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 german part,
    similar to the ep-if, ep-elseif, ..., ep-else, /ep-if structure.

    A special problem with localization is the choice of a character set.
    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 is
    throwing a Perl exception. For example, DBI handles are created with the
    RaiseError attribute set to 1, so that SQL errors trigger a Perl
    exception. You never care for errors!

    However, what happens in case of errors? In that case, EP will use the
    template that you have set with ep-errhandler and treat it like an
    ordinary 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 when
    working with ep-perl.

    You always have an object $_, which is an instance of the HTML::EP class
    (a subclass of HTML::Parser). This object has certain attributes, in
    particular `$_->{cgi}', a CGI object and `$_->{dbh}', the DBI handle.
    (Of course valid after `ep-database' only.) If you want to set or modify
    a variable, you have to set `$_->{varname}'. If you want to retrieve the
    value, use the same. Note that you cannot use `$_' for a long time, as
    it will be changed by Perl loops and the like, thus your Perl code
    typically starts with

        $_ = $self;

    But how do you access the variable from within EP documents? You just
    write

            $varname$

    This will be replaced automatically by the parser with the value of `$_-
    >{varname}'. Even more, the value will be converted into 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 special value of *varname* is `cgi': This will access
    the CGI variable of the 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? You may as
    well use

            $@varname$      (Raw)
            $#varname$      (URL encoded)
            $~varname$      (SQL encoded)

    The latter uses the $_->{dbh}->quote() method. In particular this
    implies that you have to be connected to a database, before using this
    tag!

    You can even use these symbols in attributes of EP commands. For
    example, the following will be usefull when sending a mail:

        <ep-mail subject="Howdy!" from="$@cgi->email$"
                 to="bill@whitehouse.gov">

    Attributes may include EP variables, just like ordinary HTML code. Even
    more, they may contain Perl code which is evaluated just like code
    between `<ep-perl>' and `</ep-perl>'. However, you need to use the
    variable `$_' in the code, because the package otherwise 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. But
    sometimes it is desirable to set them from within HTML. In such cases
    you 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 multiline
    variables:

      <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 custom formats
    method name, the dereferencing operator and finally the variable name.

    The above method is already predefined by the HTML::EP::Locale module.

    As you have seen, the pattern $&METHODNAME->var$ triggers the call of

        $self->_format_METHODNAME($self->{'var'});

    It is not always usefull to fix a method name. In such cases you may
    instead store a code ref in

        $self->{'_ep_custom_formats'}->{'METHODNAME'};

    For example the above could as well be

        <ep-perl>
            $_->{'_ep_custom_formats'}->{'DM'} = sub {
                my($self, $val) = @_;
                sprintf("%.2f DM", $val);
                $val =~ s/\./,/;
                $val;
            };
            ''
        </ep-perl>

  Modifying the CGI headers

    The attribute $self->{'_ep_heaaders'} is containing arguments that you
    want 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 actually
    displaying 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 an
    example.) Two problems are arising here: First of all you have to create
    your own headers. Next you *must* prevent that EP is emitting any
    output, because this might trash your images validity. Here's what 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 allows
    you to return HTML pages line by line: If your script is called
    something like nph-myscript then the server is passing the scripts
    output to the browser immediately. This is usefull, for example, if you
    display the output of a traceroute command: You'd like to see any line
    immediately, but it may take some time untill the next line arrives.

    Unfortunately NPH scripts are not well suited for HTML::EP: One of EP's
    major targets is that you need not care for errors: They may occur at
    any point but are still catched and handled by creating an error
    message. However, there's no other way to guarantee this without
    buffering output 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 its
    best to support you.

    Whenever you supply a CGI variable *debug*, then the module will enter
    debugging mode. For example if your document is `/mypage.ep', then tell
    your browser to fetch `/mypage.ep?debug=1'. You won't see the usual HTML
    page, but a plain text page with lots of debugging messages and the
    created HTML source.

    You may extend the debugging code with sequences like

        <ep-perl>
            my $self = $_;
            if ($self->{debug}) { $self->print("I'm here!\n"); }
        </ep-perl>

    Note that you should not call the *print* function directly, but the
    *print* method! The former works well in CGI environments, but EP should
    work even in other environments as well.

    But sometimes this is not sufficient: What's inserting debugging
    messages compared to using the Perl debugger? In that case you can
    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
    variable values and the like.

    However, the debug variable is obviously a security problem. For that
    reason the *debughosts* variable is present in HTML::EP::Config: You
    should set it to a regular expression matching the IP numbers of hosts
    that are allowed to enable debugging mode. The Makefile.PL should query
    for 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.

      - A glimpse based search engine in examples/glimpse.

    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.

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 takes
the method name (ep-env in out case) translates all hyphens to
underscores and adds a leading underscore. We'll see in the next
section 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 files name and a
    *contents* attribute for the files contents. The method can 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, $attr, $func) = @_;
            my $contents = $attr->{contents};
            if (!defined($contents)) { # Multiline method, no "contents"
                $func->{'default'} = 'contents'; # attribute given; return
                return undef;          # undef, until we are called
            }                          # again.
            my $file = $attr->{'file'};
            require Symbol;
            my $fh = Symbol::gensym();
            if (!open($fh, ">$file)  ||  !(print $fh ($contents))  ||
                !close($fh)) {
                die "Error while creating $file: $!";
            }
            '';
        }
        # Return an empty string:
        '';
        </ep-perl>

    The main difference to the previous example is that our method is
    prepared for being called twice: The first time with an undefined
    *contents* attribute, in which case it returns immediately, the second
    time with the value being read from the lines between ep-file and /ep-
    file.

    Note the use of the *Symbol* package when accessing files: *Never* use
    global handles like

        open(FILE, ...)

    as this might break future multithreading code!

  External extensions

    So far we have discussed only minor extensions that we did install as
    part of HTML::EP. However, this is somewhat dangerous with mod_perl:
    Suggest you have multiple virtual hosts. It might happen, that virtual
    host www.foo.com defines a method ep-file, but www.bar.net defines
    another. Thus we'd have the classical name clash.

    To prevent such a namespace pollution, EP supports external extensions
    with an inheritage model that is borrowed from Perl. Suggest we write a
    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->SUPER::init();
                $self->{'_ep_funcs'}->{'ep-shop-session'} = {
                    'method' => '_ep_shop_session'
                    };
                $self->{'_ep_shop_initialized'} = 1;
            }
        }
     
    In the HTML page we load this package as follows:

        <ep-package name="Shop">
        <ep-shop-session>

    This will do a require Shop and bless the object $self into the class
    *Shop* and call $self-init()>. Note that we allow the init method to be
    called more than once, this is important for stacking packages.

    By default packages are loaded from Perl's system directories. You can
    use the attribute *lib* to add private directories to the library search
    path. This can be relative to the servers document root, as in

        <ep-package name="Shop" lib="/perl-lib">

  Selfloader methods

    In the above examples the extension methods have been compiled
    immediately. This is not always a good idea: For example the `ep-mail'
    method is loading big external packages like *Mail::Internet* for
    sending the mail. In such cases you might wish to use HTML::EP's builtin
    self loader, which is quite similar to that of CGI. We choose `ep-mail'
    as an example:

        <ep-perl package="HTML::EP">
        my $self = $_;
        # Create a string that can be compiled for loading the method:
        $AUTOLOADED_SUBS{_ep_mail} = <<'end_of__ep_mail';
            require Mail::Internet;
            sub _ep_mail ($$) {
                my($self, $attr) = @_;
                ...
            }
        end_of__ep_mail

        $self->{_ep_funcs}->{ep-mail} = { method => '_ep_mail',
                                          default => 'body' };
        </ep-perl>

    The advantage is that you have the method available, but the performance
    penalty of loading it is almost omitted, if the method is not used.

PERFORMANCE CONSIDERATIONS
    The following are merely hints for general Perl programming, but apply
    in particular to EP programming:

    Local variables
            Use local variables instead of hash attributes, as in

                my $debug;
                if ($debug = $self->{'debug'}) {
                    ...
                }
                if (!$debug) {
                    ...
                }

            This is approximately 10-15% faster than the equivalent

                if ($self->{'debug'}) {
                    ...
                }
                if (!$self->{'debug'}) {
                    ...
                }

            Of course you win even more with any further use of `$debug'.

CHANGES
    This section describes user visible changes against previous versions.
    For details and other modifications see the `ChangeLog' file, that is
    part of the distribution.

    epparse
    epperl  In previous versions it was not possible to include EP variables or
            Perl code in attributes of EP commands, unless using a prefix
            `epparse-' 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
            whether you are using such constructs. (At least it should. :-)
            The obvious disadvantage is an incompatibility, but the new
            version is much better readable and surprisingly even (much!)
            faster, because only hash values are modified and not hash
            structures.

TODO
            mod_perl support

            Create an EP server that is accessible via a small C wrapper

AUTHOR AND COPYRIGHT
    This module is

        Copyright (C) 1998-1999     Jochen Wiedmann
                                    Am Eisteich 9
                                    72555 Metzingen
                                    Germany

                                    Phone: +49 7123 14887
                                    Email: joe@ispsoft.de

    All rights reserved.

    You may distribute this module under the terms of either the GNU General
    Public License or the Artistic License, as specified in the Perl README
    file.

SEE ALSO
    the DBI(3) manpage, the CGI(3) manpage, the HTML::Parser(3) manpage