home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright 1999 by O'Reilly & Associates, Inc.


   Show Contents   Previous Page   Next Page

Appendix F - HTML::Embperl--Embedding Perl Code in HTML

In this section...

Dynamic Tables
Handling Forms
Storing Persistent Data
Modularization of Embperl Pages
Querying a Database
An Extended Example


   Show Contents   Go to Top   Previous Page   Next Page

In This Appendix

Adapted and condensed from the HTML::Embperl manual pages by Gerald Richter

HTML::Embperl is a text processor module which takes your ASCII text, extracts embedded Perl code, executes the code, and, as far as necessary, inserts the result in your text. While Embperl can also be used with non-HTML documents, it has several features that are specifically for HTML.

This appendix gives you an overview of what you can do with Embperl. It is not a complete description of Embperl. For detailed information, please look at the documentation provided with Embperl or at the Embperl website (http://perl.apache.org/embperl/).

Embperl is not the only processor for embedded Perl code. ASP used with the ActiveState Perl port provides this for Microsoft IIS, and ePerl does this job very well for all sorts of ASCII files. There are other Perl solutions around as well. PHP is a well-known solution for easily building web pages with embedded code and database connections, but it uses its own language instead of Perl.

The main advantage of Embperl is its built-in HTML awareness. It provides features for handling form data and HTML tables, along with converting log files and error pages to HTML and linking them together. It also allows for escaping and unescaping.

Embperl can be used offline (as a normal CGI script or as a module from other Perl code), but its real power comes when running under mod_perl and Apache. It's directly integrated with Apache and mod_perl to achieve the best performance by directly using Apache functions and precompiling your code to avoid a recompile on every request.

Embperl was designed to be used with a high-level HTML editor. The Perl code can be entered as normal text (the editor need not know any special HTML tags, nor is it necessary to enter special HTML tags via uncomfortable dialogs); just enter your code as if it were normal text. Embperl takes care of unescaping the HTML entities and eliminates unwanted HTML tags that are entered into your Perl code by the editor (for example, <BR> to break lines for better readability). If you prefer to use an ASCII editor for writing your HTML code, don't worry. You can configure everything that you want Embperl to do--and everything that you don't want it to do, too. Also, on the output side, Embperl correctly escapes your HTML/URL output (as long as you don't disable it).

How can you embed Perl code in your HTML documents? There are three ways:

  • [- ... -] to execute code
[- $a = 5 -]  [- $b = 6 if ($a == 5) -]

The code between [- and -] is executed. No output will be generated. This is mainly for assignments, function calls, database queries, etc.

  • [+ ... +] to output the result
[+ $a +]  [+ $array[$b] +] [+ "A is $a" +]

The code between [+ and +] is executed and the return value (the value of the last expression evaluated) is output (sent to the browser).

  • [! ... !] to execute code once
[! sub foo { my ($a, $b) = @_ ; $a * $b + 7 } !]

This is the same as [- ... -], except that the code is only executed for the first request. This is mainly for function definitions and one-time initialization.

Comments can be entered by bracketing them between [# and #]. In contrast to normal HTML comments, Embperl comments are removed before they are sent to the browser.

Embperl supports some metacommands to control the program flow within the Embperl document. This can be compared to preprocessor commands in C. The meta commands take the following form:

[$   $]
if, elsif, else, endif
The if command in Embperl is just the same as it is in Perl. It is used to conditionally output or process parts of the document. For example:
[$ if $ENV{REQUEST_METHOD} eq 'GET' $]
  This is a GET request
[$ elsif $ENV{REQUEST_METHOD} eq 'POST' $]
  This is a POST request
[$ else $]
  This is not GET and not POST
[$ endif $]

This will output one of the three lines depending on the setting of $ENV{REQUEST_METHOD}.

while, endwhile
The while command can be used to create a loop in the HTML document. For example:
[$ while ($k, $v) = each (%ENV) $]
  [+ $k +] = [+ $v +] <BR>
[$ endwhile $]

This example will display all environment variables, each terminated with a line break.

do, until
The do and until commands also create a loop but with a condition at the end. For example:
[- @arr = (3, 5, 7); $i = 0 -]
[$ do $]
  [+ $arr[ $i++ ] +]
[$ until $i > $#arr $]
foreach, endforeach
The foreach and endforeach commands create a loop iterating over every element of an array/list. For example:
[$ foreach $v (1..10) $]
  [+ $v +]
[$ endforeach $]
var <var1> <var2> ...
By default, you do not need to declare any variables you use within an Embperl page. Embperl takes care of deleting them at the end of each request. Sometimes, though, you want to declare them explicitly. You can do this by using var:
[$ var $a @b %c $]

Has the same effect as the Perl code:

use strict ;use vars qw {$a @b %c} ;
The hidden command is used for creating hidden form fields and is described in the form field section later in this appendix.

While the Embperl metacommands give your document a more readable way of nesting control structures and give Embperl a better chance to control and log what's happening (as we will discuss in more detail later), you can also use Perl control structures inside your Embperl documents. (See the Embperl documentation for more details.)

Dynamic Tables

   Show Contents   Go to Top   Previous Page   Next Page

One very powerful feature of Embperl is its ability to process dynamic tables. This feature was designed mainly to display Perl arrays (one- or two-dimensional, regular and irregular), but it can also be used in other ways.

Here is an example that displays a Perl array:

[- @a = ( 'A', 'B', 'C') ; -]
      <TD> [+ $a[$row] +] </TD>

This example simply displays a table with three rows containing A, B, and C. The trick is done by using the magical variable $row which contains the row count and is incremented for every row. The table ends if the expression that contains $row returns undef. The same can be done with $col for columns. You can also use $cnt to create a table that wraps after a certain number of elements. This works with TABLE, SELECT, MENU, OL, DL, and DIR.

Here is a simple DBI example that displays the result of a query as a two-dimensional table with field names as headings in the first row:

# connect to database
$dbh = DBI->connect($DSN) ;
# prepare the sql select
$sth = $dbh -> prepare ("SELECT * from $table") ;
# excute the query
$sth -> execute ;
# get the fieldnames for the heading in $head
$head = $sth -> {NAME} ;
# get the result in $dat
$dat = $sth -> fetchall_arrayref ;
  <tr><th>[+ $head->[$col] +]</th></tr>
  <tr><td>[+ $dat -> [$row][$col] +]</td></tr>

Handling Forms

   Show Contents   Go to Top   Previous Page   Next Page

Another feature of Embperl is the way it helps you to handle forms. Posted form data is available in %fdat and @ffld. The hash %fdat contains the values of all form fields. The array @ffld contains the names in the order in which they were submitted.

Moreover, the HTML tags Input, Textarea, and Select take values from %fdat. If you do not specify a default value for an input tag, but a value for that input tag is available in %fdat, Embperl will automatically insert the value from %fdat and send it to the browser. This is similar to the behavior of CGI.pm. This means that if you post a form to itself, the browser will display the values you just entered.

Sometimes it's necessary to pass values between consecutive forms. One way to do this is to pass them via hidden form fields. The hidden metacommand creates hidden form fields for all fields not in another input field. This can be used to transport data through confirmation forms, for example, a wizard.

Example F-1 shows many of the possibilities of Embperl. It's a simple form where you can enter your name, your email address, and a message. If you hit the send button, you see the data you just entered and can confirm the information by hitting the "send via mail" button, or you can go back to the input form to change the data. If you confirm your input, the data will be sent to a predefined email address. The example also shows how you can implement error checking--if you omit your name or your email address, you will get a corresponding error message and the input form is shown again.

The first part is the error checking; the second part is the confirmation form; the third part sends the mail if the input was acceptable and is confirmed; the last part is the input form itself.

Depending on the values of $fdat{check}, $fdat{send}, $fdat{name}, and $fdat{email}, the document decides which part to show.

Example F-1. Input and Confirmation Form

[-  $MailTo = 'richter\@ecos.de' ;
 @errors = () ;
if (defined($fdat{check}) || defined($fdat{send}))
  push @errors, "**Please enter your name" if (!$fdat{name}) ;
  push @errors, "**Please enter your e-mail address" if (!$fdat{email}) ; 
} -]
[$if (defined($fdat{check}) and $#errors == -1)$]
delete $fdat{input} ;
delete $fdat{check} ;
delete $fdat{send}
<hr><h3> You have entered the following data:</h3>
<tr><td align="center" colspan="2">
   <form action="input.htm" method="GET">
     <input type="submit" name="send"
            value="Send to [+ $MailTo +]">
     <input type="submit" name="input" value="Change your data">
[$elsif defined($fdat{send}) and $#errors == -1$]
[- MailFormTo ($MailTo,'Formdata','email') -]
<hr><h3>Your input has been sent</h3>
<hr><h3>Please enter your data</h3>
<form action="input.htm" method="GET">
  [$if $#errors != -1 $]
    <tr><td colspan="2">
  <tr><td><b>Name</b></td> <td><input type="text"
  <tr><td><b>E-Mail</b></td> <td><input type="text"
  <tr><td><b>Message</b></td> <td><input type="text"
  <tr><td colspan=2><input type="submit"
                           name="check" value="Send"></td></tr>  </table>

   Show Contents   Go to Top   Previous Page   Next Page
Copyright 1999 by O'Reilly & Associates, Inc.