NAME

HTML::Embperl - Perl extension for embedding perl code in HTML documents

SYNOPSIS

Embperl is a perl extension module which gives you the ability to embed perl code in HTML documents (much like Server Side Includes for shell commands).

DESCRIPTION

Embperl can operate in one of four modes:

Offline

converts a HTML file with embedded perl statements into a standard HTML file.

embpexec.pl [-o outputfile][-l logfile][-d debugflags] htmlfile [query_string]

htmlfile

is the full pathname of the html file which should be processed by Embperl

query_string

is optional and has same meaning as the environment variable QUERY_STRING when invoked as CGI-Script, i.e. everything following the first "?" in an URL. <query_string> should be url-encoded. Default is no query_string.

-o outputfile

gives the filename to which the output is written. Default is stdout.

-l logfile

is optional and give the filename of the logfile. Default is /tmp/embperl.log.

-d debugflags

specifies the level of debugging (What is written to the logfile). Default is nothing. See below for exact values.

As CGI-Script

instead of directly retrieving the document from the web-server, it is processed by the CGI-Script and the result is send to the client.

embpexec.pl

If embpexec.pl is invoked without any parameters and the environment variable PATH_TRANSLATED is set, it invoke it self as CGI-Script. That means form data is taken either from the environment variable QUERY_STRING or from stdin depending on CONTENT_LENGTH (this will be set by httpd depending on the method GET or POST). Input is taken from the file pointed to by PATH_TRANSLATED and output is send to stdout. The logfile is generated at it's default location (this is configurable via the environment variable EMBPERL_LOG).

To use this mode you have to copy embpexec.pl to your cgi-bin directory. You can invoke it with the URL http://www.domain.xyz/cgi- bin/embpexec.pl/url/of/your/document.

The /url/of/your/document will be passed to Embperl by the web server. Normal processing i.e. aliasing etc. takes place before it is made to the filename contained in PATH_TRANSLATED.

If you are running apache httpd you can also define embpexec.pl as a handler for a specific file extention or directory.

Example of Apache srm.conf:

    <Directory /path/to/your/html/docs>
    Action text/html /cgi-bin/embperl/embpexec.pl
    </Directory>
From mod_perl

(Apache httpd), this works like the CGI-Script, but with the advantage that the script is compiled only once at server startup, where also other one time action (such as opening files and databases ) can take place. This will drastically reduce response times for the request. To use this you have to compile Apache httpd with mod_perl and add HTML::Embperl as PerlHandler.

Example of Apache srm.conf:

    SetEnv EMBPERL_DEBUG 2285

    Alias /embperl /path/to/embperl/eg

    <Location /embperl/x>
    SetHandler perl-script
    PerlHandler HTML::Embperl
    Options ExecCGI
    </Location>

Another possible setup is

    SetEnv EMBPERL_DEBUG 2285

    <files *.epl>
    SetHandler perl-script
    PerlHandler HTML::Embperl
    </files>

    AddType text/html .epl

Don't forget the AddType. In this setup all files with the ending epl are processed by Embperl.

See also under debugging (dbgLogLink and EMBPERL_VIRTLOG) how you can setup Embperl so you can view logfile with your browser!

As standalone process

At the moment this is only for debugging because it can only handle one request at a time, no serialization takes place if more than one client is accessing an embperl-document. This mode has the same advantage as mod_perl, because the process is once started and running (hopefully) until the web server goes down. Data from the web-server is transferred via two named pipes. The first gives the data of the request and is feeded by a small c-program which is invoked as a CGI-Script and the second transfers the output back to the CGI-Program, which sends it to the client. This mode should work in conjunction with every web server, but to really use it a serialization (and maybe a management for multiple processes must be done)

embpexec.pl -D

or

embpexec.pl if PATH_TRANSLATED is not defined as a environment variable

This start Embperl as a Daemon. You have also to copy the file embcgi to your cgi-bin directory. This program is invoked as CGI-Script by the web server. The names of the named pipe which will be used must be changed in epmain.c and embpcgi.c before compiling it and the pipes must be created by hand (i.e. mkfifo) with read and write access for both processes, before starting the processes. Input- and Formdata is the same as for the CGI-Script. Logfile outut is going to stdout.

WARNING: Everybody who has write access to the named pipe can do things as user which runs Embperl daemon. So be carefully not to run Embperl as root unless you are sure nobody else can access it.

Runtime configuration

At the moment there are a few things which could be configured at runtime. This is done by setting environment variables, either on the command line (when working offline) or in your web servers configuration file. Most http daemons understand

SetEnv <var> <value>

If you are using apache httpd and mod_perl you can use instead

PerlSetEnv <var> <value>

The advantage is that this can be used on a per directory/virtual host basis.

EMBPERL_PACKAGE

the name of the package where your code is eval in. By default Embperl generates a unique package name for every file. This makes sure variables and functions from one file can not affect the ones from another file. (But they will be still be accessable thru explict package names)

EMBPERL_OPTIONS

This bitmask specifies some options for exectution of Embperl:

optDisableVarCleanup = 1

disables the automatic cleanup of variables at the end of each request

optDisableEmbperlErrorPage = 2

tells Embperl to not send his own errorpage in case of a failure, instead giving the error back to the web server and let ot handle it the standard way Without this option Embperl sends his own error page, showing all the errors which has occured. If you have the dbgLogLink enabled, every error will be a link to the corresponding location in the log file.

optSafeNamespace = 4

tells Embperl to execute the embbeded code in a safe namespace, thus the code cannot access data or code in any other package (see the Chapter about Safe namespaces below for more details)

optOpcodeMask = 8

tells Embperl to aply an operator mask. This gives you the chance to disallow special (unsafe) opcodes (see the Chapter about Safe namespaces below for more details)

EMBPERL_LOG

gives the pathname of the log file. This will contain more or less infos about what Embperl is doing depending on the debug settings (see below). The log-output is specially intended to see what your embedded perl code is doing and to debug it. Default is /tmp/embperl.log

EMBEPRL_VIRTLOG

gives a virtual location, where you can access the embperl logfile with a browser. This feature is disabled (default) if EMBPERL_VIRTLOG is not specified. See also dbgLogLink for an Example how to set it up in your srm.conf.

EMBPERL_DEBUG

This is a bitmask which specifies what should be written to the log The following values are defined:

dbgStd = 1,

Minimum Infos

dbgMem = 2,

Memory and Scalar Value allocation

dbgEval = 4,

Arguments and result of evals

dbgCmd = 8,

Metacommands and HTML tags which are processed

dbgEnv = 16,

List environement variables

dbgForm = 32,

List form data

dbgTab = 64,

Log processing of dynamic tables

dbgInput = 128,

Log processing of html input tags

dbgFlushOutput = 256,

Flush output after every write (Should normaly not set. Only for debugging when Embperl crashs, will drasticaly slow down operation)

dbgFlushLog = 512,

Flush logfile after every line (Should normaly not set. Only for debugging when Embperl crashs, log is automatily flushed after each html file, when set will slow down operation)

dbgAllCmds = 1024,

Logs all commands and HTML tags, regardless if they are really excuted or not. (Showing a + or - to tell you if they are executed).

dbgSource = 2048,

Logs the next piece of the HTML-source which is processed. (Gives a lot of output!)

dbgFunc = 4096,

Only anvailable when compiled with -DEPDEBUGALL. Normaly only used for debugging Embperl itself. Logs all functionentrys to the logfile (lot of data!)

Inserts a link on the top of each page, which can be used to view the log for current html file. See also EMBEPRL_VIRTLOG under configuration.

Example:

    SetEnv EMBPERL_DEBUG 10477
    SetEnv EMBPERL_VIRTLOG /embperl/log

    <Location /embperl/log>
    SetHandler perl-script
    PerlHandler HTML::Embperl
    Options ExecCGI
    </Location>
dbgDefEval = 16386

Shows everytime a new perl-code is compiled

dbgCacheDisable = 32768

Disables the usage of the p-code cache. All the perl code is recompiled everytime. (Should not be used in normal operation, slows down Embperl drasticaly)

dbgEarlyHttpHeader = 65536

Normaly http-headers are send after the request was finished without any errors. This gives you the chance to set aribary http-header within the page, and Embperl the chance to calculate the content length. To do this all the output the kept in memory until the http-headers are send, and send afterwards. This flag will cause the http-headers to be send before script-processing and then the output directly without keeping it in memory (like versions before 0.18)

dbgHeadersIn = 262144

Log all http headers which are send from the brwoser

dbgShowCleanup = 524288

Show every varibale which is undef'd at the end of the request. For Scalars variables also the value is logged.

A good value to start is 2285 or 10477 if you want to view the logfile with your browser (Don't forget to set EMBPERL_VIRTLOG). If Embperl crashs (you get a Segmentation fault) add 512 so the logfile is flushed and you can see where Embperl crashs.

EMBPERL_COMPARTMENT

gives the name of the compartment from which to take the opcode mask (see the Chapter about Safe namespaces below for more details)

SYNTAX

Embperl understands four categories of commands. The first three are special Embperl command, the last category are some HTML-Tags which can trigger a special processing. Before the special Embperl-commands are processed and for the VALUE attribute of the input tag (see below), all HTML-Tags are removed and special HTML characters are translated to their ascii values (e.g. &lt; is translated to "<" ). Embperl-commands can spawn multiple lines and not necessarily starts or ends at line boundary. You can escape from this behavior by preceding the special character or HTML tag with a backslash. This is done, so you can create your embperl-html- file with your favorite (WYSIWYG) HTML-Editor, no matter if it inserts tags like line breaks or formatting into your Embperl-commands where you don't want them. All Embperl-commands starts with a "[" and ends with a "]". To get a real "[" you must enter "[[".

I am not using sgml comments (i.e. <! ... !> or similar things) because some HTML-Editors can't create them or it's much more complicated. Sinces every HTML-Editor takes [ and ] as normal text, there should be no problem.

[+ perl-code +]

Replace the command with the result of the perl code (The value returned by eval "perl-code"). As perl-code you can use everything which can be an argument to the perl eval statement (see Security below for restrictions). Examples:

 [+$a+]          replaces the [+$a+] with the content
                 of the variable $a
 [+$a+1+]        every expression can be used
 [+ $x[$i] +]    also array and hashes or more complex
                 expressions works

NOTE: White space are ignored The output will automaticly HTML escaped (e.g. "<" is translated to &lt;). You do have to care about it.

[- perl-code -]

Executes the perl-code, but delete the whole command from the HTML output.

Examples:

 [-$a=1-]        set the variable $a to one, no output
                 will be generated
 [-use somemodule-] you can use other modules
 [-$i=0; while ($i<5) {$i++} -] even more complex statements
                                or multiple statements are possible.

NOTE: Statements like if, while, for, etc. must be included in one embperl command. You can not have the if in one command block and the terminating "}" or else in another.

[$cmd arg$]

Execute a Embperl metacommand <cmd> can be one of the following (<arg> varies depending on <cmd>):

if, elsif, else, endif

everything following the if metacommand until the else, elsif or endif is only outputted if the perl expression given in <arg> is true. else and elsif works analog.

Examples:

 [$if $ENV{REQUEST_METHOD} eq 'GET' $]
 Method was GET<BR>
 [$else$]
 Method other than GET used<BR>
 [$endif$]

This will send one of the two sentence to the client, depending on the request method used to call the document.

while, endwhile

Executes a loop until the <arg> given to while is false

Example: (see eg/x/while.htm)

 [- $i = 0; @k = keys %ENV -]
 [$ while ($i &lt; $#k) $]
 [+ $k[$i] +] = [+ $ENV{$k[$i]} +]<BR>
 [- $i++ -]
 [$ endwhile $]

This will send a list of all environment variables to the client.

NOTE: The '&lt;' is translated to '<' before call the perl eval.

hidden

<arg> consists of zero, one or two names of hashs (with or without the leading %) and an optional array as third parameter. The hidden metacommand will generated hidden fields for all data contained in first hash and not in second hash. Default for first hash is %fdat and for second hash %idat. If the third paramter is specified the fields are written in the order of this array to the output file, i.e. all keys of the first hash must be in this array properly sorted. This is intended for situations where you want to pass data from one forms to the next, e.g. two forms which should be filled one after each other (e.g. an input form and a second form to review and accept the input). Here you can transport the data from previous forms within hidden fields. (See eg/x/neu.htm for an example). If you use just the hidden command without parameters it simply generates hiddenfields for all formfields submited to this document, which are not yet contained in another input field.

 Example:

    <form action="inhalt.htm" method="GET">
        <input type="text" name="feld1">
    [$hidden$]
    </form>


 If you request this with 
    
    http://host/doc.htm?feld1=A&feld2=B&feld3=C

 the output will be

    <form action="inhalt.htm" method="GET">
        <input type="text" name="feld1" value="A">
        
    <input type="hidden" name="feld2" value="B">
    <input type="hidden" name="feld3" value="C">
    </form>

NOTE: This should only be used for small amount of data, since the hidden fields are sent to the browser, which sends it back at next request. If you have large data, store it within a file with a unique name and send only the filename within the hidden field. But be aware of the fact, that the data could be change by the browser if the user didn't behave exactly as you except. Your program should handle such situations properly.

var

The var command declares one or more variables for use within this Embperl document and sets the strict pragma. The variablenames must be supplied as space separted list.

Example:

        [$var $a %b @c $]

This is the same as writing the following in normal perl code:

        use strict ;
        use vars qw($a %b @c) ;

NOTE 1: You cannot use the 'use strict' within an Embperl document, this will only aply to the block where it occurs

NOTE 2: Warnings about non declared variables will not terminate the execution of the document. It will be processed as normaly, but warning messages will be written to STDERR (httpd error log). The messages will not occur in the embperl log file

HTML Tags

Embperl recognizes the following HTML Tags (all other are simply passed through, as long as they not part of a Embperl command).

table, /table, tr, /tr

Embperl can generate dynamic tables (one or two dimensional). You only have to specify one row/column. Embperl generates as much rows/columns as nessecary. This is done by using the magic variables $row, $col and $cnt. If you don't use $row/$cnt/$cnt within a table, Embperl does nothing and simply pass the table through. Embperl checks if the varibale $row/$col/$cnt is used. Embperl repeats all text between <table> and </table>, as long the expressions in which $row or $cnt occurs is/are defined. Embperl repeats all text between <tr> and </tr>, as long the expressions in which $col or $cnt occurs is/are defined.

See also $tabmode (below) for end of table criteria.

Examples: (see eg/x/table.htm for more examples)

 [- @k = keys %ENV -]
 <table>
     <tr>
         <td>[+ $i=$row +] </td>
         <td>[+ $k[$row] +] </td>
         <td>[+ $ENV{$k[$i]} +] </td>
     </tr> 
 </table>

This will show all entries in array @k (which contains the keys from %ENV), so the whole environment is displayed (like in the while example), with the first column containing the index (from 0) and the second containing the content of the array and the third the environment variable.

This could be used to display the result of database query if you have the result in an array. You make as much columns as you need. It is also possible to call a fetch subroutine in each table row.

th, /th

th tags is interpreted as table heading. If the whole row is made of <th> </th> instead of <td> </td> it's treated as column heading. Everythingelse will be treated as row heading in the future, but is ignored in the current version.

dir, menu, ol, ul, dl, select, /dir, /menu, /ol, /ul, /dl, /select

Lists and Dropdown/Listboxes are treated excatly as one dimensional tables. Only $row, $maxrow, $cnt, $maxcnt and $tabmode are honoured. $col and $maxcol are ignored. see eg/x/lists.htm for an example.

option

Embperl looks if theres a value from the form data for a specific option in a menu. If so this option will be preselected.

Example:

<form method="POST"> <P>Select Tag</P>

    If you request this document with list.htm?SEL1=x
    you can specify that the element which has a value
    of x is initialy selected
    

    <p><select name="SEL1">
        <option value="[+ $v[$row] +]">[+ $k[$row] +]</option>
    </select></p>
</form>
input

The input tag interacts with the hashs %idat und %fdat. If the input tag has no value and a key exists with the same text as the NAME attribute of the input tag, Embperl generates a VALUE attribute which the corresponding value to the hashkey. All values of <input> tags are stored in the hash %idat, which NAME as hashkey and VALUE as hashvalue. Special processing is made for TYPE=RADIO and TYPE=CHECKBOX. If the VALUE attribute contains the same text as the value of the hash the CHECKED attribute is inserted else it is removed. So if you specify as action url the file which contains the form itself, the form will be redisplayed with same values as entered in the first form. (See eg/x/neu.htm for an example)

textarea, /textarea

The textarea tags treated excatly like other input fields (see above)

Variables scope

The scope of a variable declared with my or local is ending at the end of the [+/- ... -/+] block (if it's not in a perl { ... } block, then the scope ends at the correspondig '}', like everytime in perl ).

Global variables (everything not declared with my or local) will be undef'ed at the end of each request. So you don't have to care for any old variables lieing arround and causeing suspicious results. This is only done for variables in the package the code is evaled in (every variable that does not have an explicit package name). All variables with an explicit package name (i.e. in modules you use) will stay vaild until the httpd child process dies. Embperl will change the current package to unique name for every document, so the influence between differnet document is kept to a minimum. You can set the name of the package with EMBPERL_PACKAGE. (see also safe namespaces)

If you like to use the strict pragma, you can use the var meta command to declare your varibales.

Since cgi-scripts are always a child process on it's own, you don't have to care for that when you using Embperl as cgi-script.

If you need to declare variables which lives more the one http request (i.e. a databasehandle), you must declare then in another package (i.e. $persitent::h instead of $h).

NOTE: Bacause Apache::DBI has it's own namespace this module will also work together with Embperl an maintain your persitent database connection.

You can disable the automatic cleanup of global variables with EMBPERL_OPTIONS

Predefined variables

Embperl has some special variables which has a predefined meaning.

%ENV

contains the environment as seen from a CGI-Script.

%fdat

contains all the formdata send to the script by the calling form. The NAME attribute build the key and the VALUE attribute is used as hashvalue. Embperl doesn't matter if it's called with GET or POST method. (but there may be restrictions on the length of parameters using GET, not from Embperl but maybe from your Webserver, especialy if you using cgi-mode, so it's more save to use POST). Embperl also support multipart formdata, as it's been used for fileupload. For normal fields there is no difference to normal formdata, see docs of CGI.pm how fileupload fields are handled.

@ffld

contains all the field names in the order they where send by the browser (normally as they appear in your form)

%idat

contains all the values from all input tags processed so far.

$row

row count for use in dynamic tables (see html tag table)

$maxrow

maxium number of rows displayed in a table. This is set to 100 by default to prevent endless loops. (see html tag table)

$col

column count for use in dynamic tables (see html tag table)

$maxcol

maxium number of columns displayed in a table. This is set to 10 by default to prevent endless loops. (see html tag table)

$cnt

contains the number of tables cells displayed so far (see html tag table)

$tabmode

determintas how the end of a dynamic table is detected:

end of table

1

end when a expression with $row gets undefined (The row containing the undefined is not displayed)

2

end when a expression with $row gets undefined (The row containing the undefined is displayed)

3

end when $maxrow rows displayed

end of row

16

end when a expression with $col gets undefined (The column containing the undefined is not displayed)

32

end when a expression with $col gets undefined (The column containing the undefined is displayed)

63

end when $maxcol column displayed

default is 17 which is correct for all sort of arrays. You rarely should have to change it. The two values can be added together

$escmode

turn html and url escaping on and off (default is on ($escmode = 3))

$escmode = 3

The output of a perl expression ([+ ... +]) is html escaped (i.e. > becomes &gt;) in normal text and url escaped (i.e. & becomes %26) within a <A> tag

$escmode = 2

The output of a perl expression ([+ ... +]) is always url escaped (i.e. & becomes %26)

$escmode = 1

The output of a perl expression ([+ ... +]) is always html escaped (i.e. > becomes &gt;)

$escmode = 0

No escaping takes place

$req_rec

This variable is only available when running under control of mod_perl. It contains the request record needed to access the apache server api. See perldoc Apache for more information.

LOG

is the filehandle of the embperl logfile, by writing print LOG "something" you can add lines to the logfile. NOTE: The logfileline should always start with the pid of the currect process and continue with a four character signature delimited by a ':', which specifies the log reason.

Example: print LOG "[$$]ABCD: your text\n" ;

If you are writing a module for use under Embperl you can say

    tie *LOG, 'HTML::Embperl::Log' ;

to get a handle by which you can write to the Embperl logfile.

Namespaces and opcode restrictions

Since most web servers will contain more than one document, it is necessary to protected them against each other. Embperl does this by using perl-namespaces. By default Embperl executes every document in it's own namespace (package). This will protected documents against each other from accidently overriding the other data. You can change this behaviour (or simpily the package name) with the configuration directive EMBPERL_PACKAGE. NOTE: By explicitly specifing a package name you can access every data, also that used by another document.

If Embperl is used by more then one person, it's maybe neccessary to really protected one document against each other. Embperl gives you the possibility to use safe namespaces. Each document runs in it's own package and can't access anything out of this package. (Look at the documentation of Safe.pm for a more detailed discusion about safe namespaces)

To make a document run in a safe namespace, simply set the optSafeNamespace in EMBPERL_OPTIONS. The package name used is the same as in normal operation i.e. can be changed with EMBPERL_PACKAGE. NOTE: From the point of the executed document the code is executeed in the package main!

A second possibility to make Embperl more secure, is to use opcode restriction mask. Before you can use opcode mask, you have to setup a safe compartement.

 B<$cp = HTML::Embperl::AddCompartment ($name) ;>

This will create a new compartment with a default opcode mask and the name in $name. The name is used later to tell Embperl with compartment to use. Now you can change the operator mask. For example:

 B<$cp -> deny (':base_loop') ;>

In your configuration you must set the option optOpcodeMask in EMBPERL_OPTIONS and specify from which compartment the opcode mask should be taken by setting EMBPERL_COMPARTMENT.

 Example (for use with mod_perl):

    B<srm.conf:>

    PerlScript startup.pl

    SetEnv EMBPERL_DEBUG 2285

    Alias /embperl /path/to/embperl/eg

    <Location /embperl/x>
    SetHandler perl-script
    PerlHandler HTML::Embperl
    Options ExecCGI
    PerlSetEnv EMBPERL_OPTIONS 12
    PerlSetEnv EMBPERL_COMPARTMENT test
    </Location>

    B<startup.pl:>

    $cp = HTML::Embperl::AddCompartment ('test') ;
    $cp -> deny (':base_loop') ;

This will execute the file startup.pl on server start, which sets up a compartment named 'test', which will have a default opcode mask and additionaly loops disabled. Also the code is executed in a safe namespace.

NOTE: The package name form the compartment is NOT used!

Look at the documentation of Safe.pm and Opcode.pm for more detail information how to setup opcode masks.

UTILITY FUNCTIONS

AddCompartment ($Name)

Adds a compartment for use with Embperl. Embperl only uses the opcode mask form it, not the package name. AddCompartement return the newly created compartment, so you can allow or deny certain opcodes. See the Safe.pm documentation for details of setting up a compartment, see chapter about Safe namepsaces for details how Embperl uses it.

Example:

        $cp = HTML::Embperl::AddCompartment ('TEST') ;
        $cp -> deny (':base_loop') ;
MailFormTo ($MailTo, $Subject)

Sends the content of the hash %fdat in the order specified by @ffld to the given $MailTo adresse, with the subject of $Subject.

If you specifiy the following example code as action in your form

  <form action="x/feedback.htm" method="POST"
   enctype="application/x-www-form-urlencoded">

The content of the form will be mailed to the given email adress.

Example:

 <html>
 <head>
 <title>Feedback</title>
 </head>
 <body>
        Your data has been sccesfully send!
        [- MailFormTo ('webmaster@domain.xy',
                       'Mail from WWW Form') -]
 </body>
 </html>

NOTE: You must have Net::SMTP (from libnet package) installed to use this function.

BUGS

No known for Embperl.

Under perl5.004 there are memory leaks, this is not an Embperl Bug, but can cause your httpd to endless grow when running under mod_perl. Please upgrade to perl5.004_04 to fix this. You should also upgrade to version higher then mod_perl-1.07_01 as soon as available, because until 1.07_01 there are a memory leak in Apache->push_handler

FEEDBACK and BUGREPORTS

Please give me a feedback if you use/test this module. Bugs, questions, thinks you would find useful etc. are discussed on the mod_perl mailling list.

>From mod_perl README:

>For comments, questions, bug-reports, announcements, etc., join the >Apache/Perl mailing list by sending mail to >listserv@listproc.itribe.net with the string "subscribe modperl" in >the body.

>There is a hypermail archive for this list available from: >http://outside.organic.com/mail-archives/modperl/

SUPPORT

You can get free support on the mod_perl mailing list (see above). If you need commercial support (with a garantie for response time/a solution) for Embperl or want a web site where you can run your Embperl/mod_perl scripts without setting up your own internet www-server, please send an email to info@ecos.de.

WWW-LINKS

 mod_perl            http://perl.apache.org/
 mod_perl FAQ        http://perl.apache.org/faq
 Embperl             http://perl.apache.org/embperl.html
 apache web server   http://www.apache.org/
 see also            http://www.perl.com/CPAN/modules/by-module/Apache/apache-modlist.html

AUTHOR

G.Richter <richter@dev.ecos.de>

SEE ALSO

perl(1), mod_perl, apache httpd.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 1368:

You forgot a '=back' before '=head1'