Perl CGI
— print (last updated: Oct 15, 2009) print

Select font size:
Personalize this document by entering your login into the form in order to replace the usage of the generic LOGIN whenever relevant.
   

Eclipse Web Tools Platform

In order to create rudimentary create Web applications, we need additional support in Eclipse. The premier Eclipse software tool which provides this functionality is Web Tools Platform (WTP). It has a life of its own at
http://www.eclipse.org/webtools/
The entire thing is these 4 packages (dowload from the Computer Science server):
emf-runtime-2.5.0.zip
xsd-runtime-2.5.0.zip
GEF-SDK-3.5.1.zip
wtp-R-3.1.1-20090917225226.zip
Assuming they've downloaded to Desktop, install with this sequence:
$ cd ~/Desktop
$ sudo unzip -qo emf-runtime-2.5.0.zip -d /usr/local/
$ sudo unzip -qo xsd-runtime-2.5.0.zip -d /usr/local/
$ sudo unzip -qo GEF-SDK-3.5.1.zip -d /usr/local/
$ sudo unzip -qo wtp-R-3.1.1-20090917225226.zip -d /usr/local/

Install perl-cgi Eclipse project

The archive file you want is perl-cgi.zipwhich needs to be extracted as the directory
~/public_html/perl-cgi
If you download it to Desktop, then proceed as follows:
$ cd ~/Desktop
$ unzip perl-cgi.zip -d ~/public_html/
Open Eclipse and Create a New Perl Project. We want to do this:
  1. In the popup window, uncheck the Use default location checkbox.
  2. Browse to set the Location to the ~/public_html/perl-cgi directory.
  3. Set the Project name to perl-cgi. Click Finish.
Make sure you get a directory listing from:
http://localhost/~LOGIN/perl-cgi/

CGI programming

CGI (Common Gateway Interface) is a protocol by which any programming language can be used to process browser and other HTTP requests and transmit the results back to the browser. Perl/CGI may not be as fast as necessary; however, the performance can be significantly enhanced by using FastCGI or other related techniques.

A CGI program accepts requests and input data through its progamming environment variables (see the CGI Environment discussion below). The program then generates a content header followed by HTML (or other) content and sends it to the browser via standard output.

The following "hello world" Perl program is a simple starter script.

hello.cgi
#!/usr/bin/perl -w print "content-type:text/html\n\n"; print "Hello from the Perl/CGI script <b>$0</b>\n";
The CGI environment represents the values available to CGI programs by which the program communicates with the Web server. In Perl, the global hash %ENV provides access to the environment. Here are some examples: The following simple CGI script prints the environment:

printenv.cgi
#!/usr/bin/perl -w use strict; print "content-type:text/html\n\n"; foreach my $key (sort keys %ENV) { print qq(<b>$key</b> => $ENV{$key}), "<br />\n"; }
Try the browser executions of hello.cgi and printenv.cgi, seen directly as these URLs:
http://localhost/~LOGIN/perl-cgi/hello.cgi
http://localhost/~LOGIN/perl-cgi/printenv.cgi
A CGI program on a Linux system should be able to successfully execute on the command line, although sometimes this may fail because the shell enviroment is different from the CGI environment. Try these from the shell in the directory:
$ cd ~/public_html
$ ./hello.cgi
$ ./printenv.cgi

The Perl CGI package (CGI.pm)

The CGI package provides functions used to simplify the retrieval of query parameters and generation of HTML code. Some authors prefer not to use it, favoring the direct generation of HTML code. However, with experience and selectivity, these functions serve you well.

As can be expected, the CGI package provides multiple ways to use its functions. Probably the easiest way to use CGI is to import one or more of its function groups specified by the %EXPORT_TAGS variable. The four main exportation groups are these:
':html2' => h1, h2, h3, h4, h5, h6, p, br, hr, ol, ul, li, dl, dt, dd,
            menu, code, var, strong, em, tt, u, i, b, blockquote, pre,
            img, a, address, cite, samp, dfn, html, head, base, body, 
            Link, nextid, title, meta, kbd, start_html, end_html,
            input, Select, option, comment, charset, escapeHTML

':html3'=>  div, table, caption, th, td, TR, Tr, sup, Sub, strike, 
            applet, Param, embed, basefont, style, span, layer, 
            ilayer, font, frameset, frame, script, small, big
		
':form' =>  textfield, textarea, filefield, password_field, hidden, 
            checkbox, checkbox_group, submit, reset, defaults, 
            radio_group, popup_menu, button, autoEscape, scrolling_list, 
            image_button, start_form, end_form, startform, endform,
            start_multipart_form, end_multipart_form, isindex, 
            tmpFileName, uploadInfo, URL_ENCODED, MULTIPART
		
':cgi' =>   param, upload, path_info, path_translated, url, self_url, 
            script_name, cookie, Dump, raw_cookie, request_method, 
            query_string, Accept, user_agent, remote_host, content_type, 
            remote_addr, referer, server_name, server_software, server_port,
            server_protocol, virtual_host, remote_ident, auth_type, http, 
            save_parameters, restore_parameters, param_fetch, remote_user, 
            user_name, header redirect, import_names, put, Delete, Delete_all, 
            url_param, cgi_error
The important standard group is composed of these groups:
':standard' => :html2 :html3 :form :cgi
Additionally, all functions are in the @EXPORT_OK array, and so can be imported individually.

If you observe the first three groups, you'll see a generating function for virtually every HTML element. This is a convenience which can sometimes be overused. Nevertheless, it is convenient not to have to type so many < and > characters needed in HTML syntax.

Using the CGI functions

Below are two versions of a simple "hello world" CGI script using the CGI.pm package. The difference between the programs is the manner in which the package functions are used.

My personal preference is the first one, hello1.cgi which imports according to the group specified by the :standard export tags. The downside of this approach is the name pollution effect, i.e., importing a large group of predefined functions. For example, the Perl reset function is overridden by a CGI function of the same name.

hello1.cgi
#!/usr/bin/perl -w use CGI qw( :standard ); use CGI::Carp qw( fatalsToBrowser ); print header; print start_html { title => "hello 1" }; print h3 { style => 'text-align:center' }, "hello 1"; print end_html;
The script hello1.cgi makes use of four common CGI functions: header, start_html, h3 and end_html explained below. Here are the program notes:
  1. The CGI::Carp package usage allows runtime errors to be displayed in the browser.
  2. The header() function, called with no arguments. is equivalent to this:
    print "Content-Type: text/html; charset=ISO-8859-1\n\n";
    
    The header call is the only one which is strictly necessary since it is part of the HTTP protocol, without which the browser will choke.
  3. The start_html function, called with a hash reference parameter setting a value for title is equivalent to this:
    print << ENDPR
    <?xml version="1.0" encoding="iso-8859-1"?>
    <!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
    <head><title>hello 1</title></head>
    <body>
    ENDPR
    ;
    
  4. The h3 function is called with a hash reference and string. The key/value hash pairs in the hash reference are used to set attributes in h3 tag. This is the equivalent:
    print qq( <h3 style="text-align:center">hello 1</h3> );
    
  5. The parameter-less end_html function is equivalent to:
    print "</body></html>";
    
The second version, hello2.cgi, uses the object-oriented approach favored by many authors. The downside (?) of this approach is that it forces you to use parentheses around any CGI function call which has one or more parameters.

hello2.cgi
#!/usr/bin/perl -w use CGI; use CGI::Carp qw( fatalsToBrowser ); my $cgi = CGI->new; # my $cgi = new CGI; # alternative call to the CGI::new function print $cgi->header; # OK to skip parentheses if no arguments print $cgi->start_html( { title => 'hello 2' } ); # must use parentheses! print $cgi->h3( { align => 'center' }, 'hello 2' ); print $cgi->end_html;

Web programming inputs

Parameters (so called GET parameters) are passed to a script in the query string as follows:
http://.../SCRIPT?name1=value1&name2=value2&...
A parameter whose name appears more than once is called multi-valued, otherwise, it is single-valued. The CGI.pm param function can be used in different ways to obtain all the information about the parameters:
  1. If param is used with no arguments in a scalar context, like this:
    $num = param();
    
    Then $num is the number of parameters (if there are none, $num is "").
  2. If param is used with no arguments in array context, like this:
    @param_names = param();
    
    Then @param_names is the list of all parameter names.
  3. If param is used in a scalar context with a single argument, like this:
    $first_value = param('name');
    
    Then $first_value is the first value listed with the parameter 'name'.
  4. If param is used in an array context with a single argument, like this:
    @all_values = param('name');
    
    Then @all_values is the list of all values with the parameter 'name'.
Most common usage is my $a = param('a') where we use a variable of the same name as the known parameter.

The script params.cgi below illustrates how parameters passed to a CGI script, say, through the query string, can be accessed using param function. Activate the script by itself
http://localhost/~LOGIN/perl-cgi/params.cgi
and then activate it with the following query strings added to the URL:
?a=1    ?b=2    ?a=1&b=2&c=3    ?a=1&b=2&a=3

params.cgi
#!/usr/bin/perl -w use strict; use CGI qw( :standard ); use CGI::Carp qw( fatalsToBrowser ); print header; print start_html { title => "show params" }; my @params = param; # array context, the list of all parameters print "number parameters: ", scalar(@params), br, "\n"; print "parameters: @params"; # normally, we're expecting certain parameters my $a = param("a"); my $b = param("b"); my $c = param("c"); my @all_a = param("a"); print h4("Values of specific parameters:"), "\n"; print "a: ", ((defined $a) ? $a : "UNDEFINED"), br, "\n"; print "b: ", ((defined $b) ? $b : "UNDEFINED"), br, "\n"; print "c: ", ((defined $c) ? $c : "UNDEFINED"), br, "\n"; print "all_a: @all_a"; print end_html;
You can also run params.cgi in the shell and pass parameters as follows:
$ ./params.cgi "a=1&b=2&a=3"

AJAX/jQuery activation

We're going to use JavaScript to activate the server-side scripts and display the results in a web page. The activation can be triggered will be triggered by a button, parameters will be passed to the script and the output will be displayed.

There are many, many so-called client-side packages (i.e., JavaScript packages) which can do the trick, but the one we'll use is called jQuery. One advantage of the style in jQuery is that all the JavaScript code can be placed in external files. The homepage for jQuery is:
http://www.jquery.com
We need to download, install and make available the latest JavaScript file. A recent version is available from the Computer Science server as:
jquery-1.3.2.min.js

System-wide JavaScript URL

We're going to use the directory /usr/local/share/javascript as the system-wide directory corresponding to the URL "http://localhost/javascript". Change to the download directory (probably Desktop) and do this:
$ sudo mkdir /usr/local/share/javascript
$ cd ~/Desktop
$ sudo mv jquery-1.3.2.min.js /usr/local/share/javascript/
$ cd /usr/local/share/javascript/
$ sudo ln -s jquery-1.3.2.min.js jquery.js
In particular, we want to access jQuery as the URL /javascript/jquery.js. Next, we must set up the Apache alias. To do so, create the file /etc/apache2/conf.d/aliases.conf (there will eventually be more than one alias here). This should be the content:
<Directory /usr/local/share>
  Options FollowSymLinks
  AllowOverride None
</Directory>

Alias /javascript /usr/local/share/javascript
Afterwards, reload Apache:
$ sudo /etc/init.d/apache2 reload

JavaScript debugging

Firefox's built-in debugger is the Error Console, which is often acceptable in itself. One accesses the error information through Tools Error Console.

Additionally, install Firebug (use the link and follow instructions). Firebug will give much more detailed errors/warnings and will reveal the JavaScript-generated code. Once installed, access it by: Tools Firebug Open Firebug.

Example: command activation

We want the experience of creating an HTML file, the accompanying JavaScript activation file, and the Perl/CGI server-side file. We'll use the perl-cgi project as the location along with eclipse. In all cases it's best to actually key in the code (the empty HTML file's structure is pre-created) so that you can experience Eclipse's editor assists and learn the languages better.

We want to create the file command.html and so right-click on the perl-cgi project and select:
New Other Web HTML
and click Next. Enter it the name command.html (or just command, the ".html" will be added). Then Finish. Modify the content to be this:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
              "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Command</title>
<script type="text/javascript" src="/javascript/jquery.js"></script>
<script type="text/javascript" src="command.js"></script>
</head>
<body>
<input type="text" id="cmd" />
<button id="run">Run Command</button>
<hr />
<div id="show"></div>
</body>
</html>

Next, create a new JavaScript file command.js analogously using the sequence:
New Other JavaScript JavaScript Source File
Modify the content to be this:
$(document).ready(
  function() {
	  
    $("#run").click( 
      function() {
        $.get(
          "command.cgi",
          { cmd : $("#cmd").val() },
          function(data) {
            $("#show").html(data)
          }
        )
      }
    )
    
  }
)

Finally, create a new Perl/CGI file command.cgi analogously using the sequence:
New Perl File
You have to specify the .cgi suffix when you name this file. Modify the content to be this:
#!/usr/bin/perl

use strict;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);

print header;

my $cmd = param('cmd');

print h4( {style=>'color:red'}, qx(date) );
print b("command executed: "), tt($cmd);

my $output = qx($cmd);
if ( $? != 0 ) {
  print h4 "*** command error ***";
}
else {
  print pre escapeHTML $output;
}

Change directory to this project directory, make command.cgi executable and test the executability of the script:
$ ./command.cgi "cmd=ls"
Next, run command.cgi as this URL:
http://localhost/~LOGIN/perl-cgi/command.cgi?cmd=ls
If everything is OK, run command.html. Type "ls" into the field and press the button.
http://localhost/~LOGIN/perl-cgi/command.html

Discussion

Inserting server-side output into HTML

Text obtained from server-side output may contain special characters which need to be dealt with, or escaped before inserting into HTML. All special characters in used in HTML have character sequences beginning with "&" and ending with as semicolon. The two most pressing replacements are < by "&lt;" and & by "&amp;". Additionally, it's important to replace the double-quote by its special sequence, "&quot;" for usage as a quoted textfield's value.

Programming languages used for server-side output always provide a special function for this purpose. In the case of Perl/CGI, the function is escapeHTML which makes these replacements:
<       &lt;
&       &amp;
"       &quot;
'       &#39;
>       &gt;
Our command.cgi script uses it in the line:
print pre escapeHTML $output;

Explanation of the jQuery usage

The JavaScript code used is a specialized subset of JavaScript dictated by the jQuery package. The jQuery package has the advantage of being usable without having to modify the HTML. The only requirement of the HTML code is that key elements specify certain attributes, of which, the most basic is the id attribute (which is unique to the element). In our case: The event of interest is the button click. In jQuery notation, $("#run") indicates the element with id="run", namely the button. We want to define what happens on clicking this, which, in jQuery terms, means giving a definition of $("#run").click(...).

According to the jQuery usage logic, all the event-handling definitions are enclosed within the structure:
$(document).ready(
  function() {
    ...
  }
)
This indicates that the event-handling functions definitions can only be set after the document is fully loaded (i.e. ready) when all elements have been defined. If your JavaScript code employs other helper functions, these would be defined outside this structure.

The corresponding JavaScript code
$("#run").click( 
  function() { ... }
)
indicates to execute the function inside when the button is clicked. The function executed is an AJAX-style GET activation:
$.get( 
  "command.cgi",
  { cmd : $("#cmd").val() },
  function(data) {
    $("#show").html(data)
  }
)
The first argument indicates the server-side script "command.cgi" to call. The second argument is a JavaScript object listing the parameters to pass to the GET activation and there values. The general form is
{ param1: value1, param2: value2, ... }
The value of the cmd parameter is the value extracted from the textfield (the element with id="cmd"). jQuery uses the val() function to obtain this value. The last argument is the callback function, indicating what to do when the server-side call is complete:
function(data) {
  $("#show").html(data)
}
The data parameter in this function represents the standard output sent from the server-side call. The $("#show") indicates the element with id="show", namely the div element. The function .html(), used in this way with data passed as an argument, means to replace the HTML content within this element by data.

Putting it all together: when the button is clicked, the textfield's value is read and passed as the cmd parameter to the server-side command.cgi script; upon complettion, the HTML content of the div element is to the output of the server-side call.


© Robert M. Kline