Windows users: CGI files generated with DOS/Windows must have a first line which ends in "-w" (as in the examples below) if they are executed on a Unix server. If you omit the "-w", Unix will stumble over the Windows newline character and return a server error.

1 CGI - Common Gateway Interface

1.1 A simple CGI script

A webserver must be CGI enabled for CGI scripts to run. The instructions below may have to be adapted to work on any particular webserver.

In general, you need two directories: "public_html" and a subdirectory of "public_html" called "cgi-bin". The public_html directory should be world readable and executable. The cgi-bin directory should be executable but not readable. You may also need to change the permissions for your top level directory. The following commands create the directories and set the permissions. You should copy and paste the following commands at the Unix prompt (not as a Perl script). You need to do this only once. If you already have a public_html directory, skip the second line.

cd; chmod 711 .;
mkdir public_html; chmod 755 public_html;
cd public_html; mkdir cgi-bin; chmod 711 cgi-bin;

All html files should be in the public_html directory, all cgi files in the cgi-bin directory. The URL for the html files is
http://www.student.soc.napier.ac.uk/~username/filename. The URL for cgi files is
http://www.student.soc.napier.ac.uk/~username/cgi-bin/filename

1.2 Exercises

1) Save some simple html code such as

<html>
<head><title>Hello World</title></head> <body>
<h1>Greetings</h1>
</body></html>

as a file in your public_html directory on the webserver. The file permissions of this file should be -rw-r--r--. Type ls -l to check the file permissions. You can set the permissions with chmod 644 filename. Now, look at the file through your browser.

2) Save some simple cgi code such as

#!/usr/local/bin/perl -w
########################
use CGI qw(:standard -debug);
########################
print header();
print <<EOS;
<html>
<head> <title>Hello World</title> </head> <body>
<h1>Greetings</h1>
</body></html>
EOS

# if you are editing this on a PC, you'll need this line after EOS

in your cgi-bin directory. Run "perl" on the file to check the syntax. (Hit Control-D if it asks you to enter the form values.) The file permissions should be -rwx------. You need to change the file permissions with chmod 700 filename or with chmod 755 filename, depending on how the webserver is setup.

Notes:

  • "print header()" is the same as print "Content-type: text/html\n\n"; but it leads to fewer mistakes.
  • It is safer to use #!/usr/local/bin/perl -Tw as the first line of your code. But then you need to type perl -T on the command-line to check the syntax. (Or add "alias perl 'perl -T'" to your .login file).
  • A string can be delimited using "<<SOMETHING; ...SOMETHING" instead of using double or single quotes. The advantage is that quotes can be used within the string. But there must be no whitespace after SOMETHING. And there must be a blank line after SOMETHING if it occurs at the end of a file edited on a PC.
  • For security reasons the following lines should be added to any cgi file after the line with "use CGI ...".

    use CGI::Carp qw( fatalsToBrowser );         ######## for debugging info in the browser
    $CGI::POST_MAX=1024 * 100;                ######## max 100K posts
    $CGI::DISABLE_UPLOADS = 1;            ######## no uploads

  • "use strict" can be added to require all variables to be declared with "my".

    1.3 Tips for dealing with an "Internal Server error":

    1) The first line of the script must contain the perl command (#!/usr/local/bin/perl -w). For CGI files generated on DOS/Windows: the "-w" is necessary!
    2) The line "use CGI qw(:standard);" must be somewhere at the beginning.
    3) The very first print statement of your script must be "print header();"
    4) The file permissions must be set to executable.
    5) The script should be executed on the command line to check the syntax.

    2 Processing forms with CGI

    Normal HTML:

    browserserver
    user requests
    html document
    server finds HTML file
    and sends page back

    CGI:

    browserserver
    user requests
    a form
    server finds the HTML form
    and sends it back to user
    user fills out form
    CGI application executes
    program and sends results
    back to user

    2.1 A sample form

    <form action="http://www.student.soc.napier.ac.uk/~username/cgi-bin/example" method="post">

    <input type="radio" name="drink" value="tea" checked > Tea <br>
    <input type="radio" name="drink" value="coffee" > Coffee <br>
    <input type="radio" name="drink" value="hot chocolate" > Hot Chocolate <p>

    <input type="submit" value="Place order">
    </form>

    2.2 Exercises

    3) Include the form in an html document on the webserver (don't forget to change the URL of the form action so that it points to your cgi-bin directory).

    2.3 Source code of a form processing cgi file

    #!/usr/local/bin/perl -w
    ########################
    use CGI qw(:standard -debug);
    ########################
    print header();
    print <<EOS;
    <html>
    <head><title> Tea is served</title> </head><body>
    <hr><h1> Tea Room</h1><hr><p>
    EOS

    my $drink = param("drink");

    if ($drink eq "tea") {
          print "You requested tea.";
    }
    elsif ($drink eq "coffee"){
          print "You requested coffee.";
    }
    elsif ($drink eq "hot chocolate"){
          print "You requested hot chocolate.";
    } else {
          print "An error occurred.";
    }
    print <<EOS;
    <p>Thank you for your visit. Please come again. <p><hr>
    </body></html>
    EOS

    2.5 Exercises

    4) Save the cgi file. Run Perl on it to check for syntax errors. It will ask you to input parameters manually. Type "drink=tea" then "enter" and then hit Control-D. Then check to see if it works via the browser and with the form from the last exercise. Change the form action method from "post" to "get" and observe how this changes the query string.

    5) Add a checkbox to the form (such as "Do you want milk? Yes/No") and a text area where customers can type in what kind of cake they would like to order. Change your cgi script so that it includes these in its reply, such as "you requested tea with milk", "sorry we are out of chocolate cake". The checkbox and text area must have distinct names in the form. Their parameters are retrieved in the cgi file by using the "param()" function.

    Optional Exercise:
    Incorporate both the form and the CGI into the same file.

    3 On-line greeting cards

    On-line greeting card services often involve several pages: An HTML page lets a user select an image for the greeting card. For example, the following HTML code, lets a user choose one out of four images:

    Select a picture:
    <p>
    <A HREF="http://www.student.soc.napier.ac.uk/~username/cgi-bin/greeting?image=1">
    <img src="image1.jpg"></a><p>
    <A HREF="http://www.student.soc.napier.ac.uk/~username/cgi-bin/greeting?image=2">
    <img src="image2.jpg"></a><p>
    <A HREF="http://www.student.soc.napier.ac.uk/~username/cgi-bin/greeting?image=3">
    <img src="image3.jpg"></a><p>
    <A HREF="http://www.student.soc.napier.ac.uk/~username/cgi-bin/greeting?image=4">
    <img src="image4.jpg"></a><p>

    All four URLs link to the same CGI file ("greeting") which uses a parameter ("image") to distinguish between the four images. This cgi file should produce a form with textboxes for the recipient's email address, the recipient's name and the message.

    Upon submitting this form a second CGI file is invoked, which sends an email to the recipient. The code below gives some indication about how to send an email. Note: sending email messages is a potential security risk. At Napier you can send emails from cgi scripts but only within the firewall. The code below is purposefully provided in a form which will not work on DCS. To use this code you need to know enough about Unix to make some modifications. All user input needs to be checked carefully before sending mail. There are Perl libraries (Mail::CheckUser or Mail::Verify), which you can download from cpan.org. If you don't know how to do this, then don't use email in cgi scripts.

    open(SENDMAIL, "|/usr/lib/sendmail -oi -t)
          or die "Can't fork for sendmail: $!\n";
    print SENDMAIL <<EOF;
    To: somename\@napier.ac.uk
    From: User Originating Mail <yourname\@napier.ac.uk>
    Subject: A relevant subject line

    Body of the message goes here, in as many lines as you like.
    EOF
    close(SENDMAIL);

    3.1 Exercises

    6) For the greeting card example, write a cgi script that prints "you have selected image ..." and the number of the image selected. Then the cgi script prints textboxes for the recipient's email address, the recipient's name and the message.

    7) The greeting card example shows that parameters can be added to a URL (for example "greeting?image=3"). Try what happens if you enter parameter values other than 1, 2, 3 or 4. Add an if statement to your cgi script that prints "not an acceptable selection" if the image number is not 1, 2, 3 or 4.