Things to know about Perl and CGI:

CGI Programming

The critical problem of programming with the Internet


Most modern programming languages are interactive.
That is, they count on interaction with a user.
Users are used to this type of program and expect it. (I click a button, omething should happen)
The interface we are dealing with is the web page. All interactions with the user happen through the web page.
Remember from earlier in the semester that the http connection from the client to the server remains open ONLY while a page is being loaded into the client machine.
If I write a program and it lives on klingon, how will it get to your machine at home?
How can we get your web pages to interact with my program?

The CGI (Common Gateway Interface)


One of the best ways to make a program work over the internet is called
CGI programming
In this technique, all programs reside on the SERVER. The client only deals with straight html documents.
The CGI is simply a standard which legislates how a program will get information from a web page.
It is NOT a programming language
It is a way of transferring information from a server program to and from a client browser.

Data encoding


It is simplest to transfer information as one long string
CGI uses a special coding technique to create this string
The coding eliminates spaces, concatenates object values, and translates certain special characters into hex values.
The program needs to be able to decode the information again so it is easier to work with. It is usually seperated into variables
Most programmers use a library (see cgi-lib below) to make this easier

The three main ways the CGI works:

Ismap


Syntax: Add the ISMAP element to an <img> tag:
Example: <img src = "usamap.gif" ISMAP)
Used for server - side image maps
Sends the X Y coordinates of the pixel the user clicked on to the map file
As noted, messy and difficult
Don't worry too much about using this technique

Get


Used in the method attribute of a form tag
Requires an attribute action of the form that states the URL of the program that will work with the information
Sends the data to the program as part of the URL (as a long encoded string)
Only useful for very small pieces of information
Not always supported by CGIwrap

Post


Preferred method
Used in the action attribute of a form tag
Requires an action attribute of the form that states the URL of the program that will work with the information
Sends information to <STDIN> as a long encoded string
Nearly any languge can read standard input as a file
Works with cgiwrap

CGIWrap

Discussion


Because cgi programs are executable programs, they traditionally need to be in a special part of the server, called the cgi-bin directory
Each server has only one of these directories, and only the System Administrator has access to it.
Badly written or malicious programs could reek major havoc
cgiwrap is a special feature on our server that allows us to each have our own cgi-bin directory.
When we call our cgi programs, klingon's cgi wrap program will first test them to
make sure they don't do anything dangerous to the system
The biggest advantage to us is that we maintain control of our own cgi-bin directory and programs. We don't have to ask permission every time we want to add a cgi program.

Creating your cgi-bin


Go to your public_html subdirectory
Create a new subdirectory called cgi-bin
Give this subdirectory 755 permission

Calling a program via cgi wrap


If I (aharris) have a program in my cgi-bin called "foo.pl";
Make sure it has 711 or 755 permission
The url for this file would be :
http://klingon.cs.iupui.edu/cgi-bin/cgiwrap/aharris/foo.pl
Notice that you would put your own userid instead of aharris
Also note that there is no tilde in front of the userid. (!)
That's because this is an absolute reference from klingon's root

To send the contents of a form to a perl script under cgi:


Set the form's action attribute to the url of your perl script
Set the form's method attribute to "post"

4.Perl

Programming languages for CGI


You can write a cgi program in any language that works on your server.
Since our server is based on unix, we have to use a unix based programming language.
The most popular language in unix is c/c++
C is TERRIBLE for working with strings (text)
All CGI input/output is in string format
Thus, C/C++ is not the best language for CGI work

Why Perl?


Loosely based on C and various unix utilities
Allows much simplified access to string information
Very popular as a cgi language

When to use it:


When you need server-side capablities
File Handling
Details that won't work on client
You have some kind of cgi access

Essential Perl Characteristics

Variables


Variables in Perl usually start with a $ or a @ character.
We are mostly concerned with the ones that start with a $
These ($) variables are called SCALARS in perl
Variables that start with @ are arrays.
Perl does not distinguish between numeric and text variables
Perl does not require variables to be declared before they are used

Comments


Comments in Perl begin with a # sign

Input


When Perl programs are NOT used for CGI, they usually rely on <STDIN>as the main input source.
They can also get input from files, or environment variables
When used in CGI scripts called via the GET action, Perl gets input from environment variables. (specifically, one called $ENV{'QUERY_STRING'})
When used in cgi scripts called via the PUT action, Perl gets input from <STDIN>
Most of the time, our input and output will be done through CGI libaries (see below)

Output


The main output command for perl is print
If the first print line specifies the output will be html, the output will be
interpreted by the browser as html.
The line that does this in perl is the following:
print "Content-type: text/html \n \n";
(The \n characters stand for newline, forcing a carriage return)
The print statement can print out text, numbers, or the values of variables
Most of the time, our input and output will be done through CGI libaries (see below)

Conditions


Conditions in perl follow c conventions for the most part
The condition is enclosed in parentheses
Conditions usually compare values to variables or two variables to each other

Examples


($name eq "wally")
(upCase($name) ne "QUIT")
($answer == 5)
($answer != $correct)
($guess > 10)
Note that there are different operators for text and numeric comparison
Most of the other comparison operators are familiar to c/c++/javaScript programmers

If - else structure


The main branching structure in perl is very similar to that in c/c++

Example


if ($name eq "Wally"){ #does $name equal "Wally"?
print "Wally, you are a PIG"; #if so, call him a
#name
}else { #if not...
print "Do I know you, ",$name, "?"; #make a more
#polite greeting
}; #End the if structure

Example 2


#The else clause is optional. Examine this code:
$answer = 3 #Initialize $answer to 3
if ($answer == 5){ #if $answer is equal to 5...
print "Correct!"; #say so
}; #(else do nothing) end if

While structure


The main looping structure also works similarly to its cousin in c and javascript

Examples


$counter = 1; #initialize counter to 1
while ($counter < 10){ #as long as $counter is less
#than 10...
print $counter; #print out the value of counter
$counter++; #increment the counter
}; #end while structure

For loop


The for loop will also be completely familiar to c/javascript programmers;

Examples:


for ($counter =1;$counter <=10;$counter++){
print $counter;
}; # end for loop

for($counter = 10;$counter >=0;$counter--){
print $counter;
}; #end for loop

Using a library

Cgi-lib.pl


The defacto standard code library
A bunch of tools for using perl with CGI
Eliminates the need to do complex pattern matching - etc to decode form info

Purpose


Puts the common jobs you need into subprograms
The subprograms act like specialized commands
Allow you to think in 'cgi' without knowing as much perl
Hide some of the scary things (like data unpacking) from programmer
Read the comments in cgi-lib for ideas on how to use the code
Note that you don't need to understand everything about how it works,
You do need to understand what it can do and how to use it.

Key routines in cgi-lib.pl

print &PrintHeader


prints a standard content-type header
The syntax for content-type is VERY picky
print &PrintHeader is much easier to use
It needs to happen before you try to write code to the page

print &HtmlTop


A nice convenient way of forming the top part of a web page.
You can send it a parameter and it will put that value in the title as
well as inside a pair of <h1> tags

print &HtmlBot


Gives the standard bottom of an html page.
Useful because it protects you from memorizing this syntax
Not as critical as &printheader, but still handy

&ReadParse


The most critical routine in cgi-lib!
Decodes the form information from get or put
places it into a special variable array
You can read the elements of the array into separate variables
The easiest way to work with values from a form
It doesn't matter at all how the value was indicated by the user
It will just be a controlname - value pair

typical perl program using cgi-lib



#!/usr/local/bin/perl

#first line points to my perl interpreter
#sample.cgi by Andy Harris, 2/17/97

#load up the cgi library
require "cgi-lib.pl";

#get values from form, place them in array called input
&ReadParse (*input);

# in this case, we will assume that our form had textboxes named
# txtName, txtEmail, and txtMessage. We will place the values
# of these fields into plain old variables for ease of use.

# Grab the value related to txtName in the input array, copy that
# value to $userName
$userName = $input("txtName");

# Do the same with Email and Message
$userEmail = $input("txtEmail");
$message = $input("txtMessage");

# Make a page to print out the results

# Print out the standard content-type header
print &PrintHeader;

# print out some standard html
print "<html><head><title>Results</title></head>";
print "<center><h1>Results:<hr></h1></center>\n";

# print out first variable
print "The user's name was: ";
print $userName;

#print a newline to the OUTPUT
print "<br>";

# print out a newline character to the SOURCE code
print $ "\n";

# print out second variable using concatenation
print "Email address: " + $userEmail + "<br>\n";

# print out third variable with interpolation
print "Message: $message <br>\n";

# print out some finishing stuff
print "<hr>\n";
print &HtmlBot;

Important perl capabilities

Pattern Matching

General concepts


allows you to look for a certain pattern in a string
special operators allow for VERY powerful searches
pattern matching can be complex but powerful
Basic syntax:
$variable =~ match_type/search_value/replace_value/operator
where $variable is the variable you are playing with
match_type is m for match, s for substitute, or t for translate
search_value is the value you are looking for in the string
replace_value is a value you use for replacement.
Operator is a value that might modify the search or replacement

The Match


uses the m operator
Usually looks something like this:
if ($program =~ m/ant/);{
print "There's a bug in this program!";
}
Often part of an if statement
The m/ / gives back a true or false value only.

Sometimes used to check that a value is within a certain range.
The following code will return true if the value of $answer has numeric values
$answer =~ m/[0-9]/

We might need another trap to make sure there are no Alphabetic characters. This code would do that:
$answer =~m/[^A-Za-z}/
The ^ sign indicates we want to know if there are NO alphabetic characters.
Note that we have to check separately for upper and lower case.

The two might be combined like this:
if (($answer =~m/[0-9]/) && ($answer =~[^A-Za-z])){
print '$answer is valid'
}else{
print '$answer is not a number')
}# end if

note that m is the default pattern operation. Some programmers leave it out.
The following two lines are the same:
if ($line =~ m/john/){
if ($line =~/john/){

When you use the m, you can change the \ to anything else you want, so
if($line =~ m@john@){
means the same thing. (WHEW!)

Substitute


uses the s parameter
Often looks like:
$myvariable =~ s/coffee/tea/gi;
looks in the variable $myvalue and replaces every occurrence of "coffee" with "tea"
the g says "do it globally, throughout the entire file
the i means "ignore case"
g and i are optional.
Commonly used to force <br> tags into textarea variables, like this:
$stuff =(*input('txaStuff');
$stuff =~ s/\n/<br>\n/g;

This line will look for the newline character (\n to perl) and translate it to an html br tag and a newline.

Translate


Rarely used. S/ / / is more useful

Thoughts on pattern matching


It can get VERY complex.
Most of the things you want have been done already
Read and borrow code that does what you want.

For more information:


read a book on regular expressions, especially
Perl 5.0 CGI Web Pages (Hagey, Ziff - Davis, 1996)
Programming Perl (Wall/Schwartz, O'Reilley and Assoc., 1992) BTW, Wall WROTE perl (!)
Perl 5 by Example (Medinets, Que, 1996)
or check the web for regular expressions, perl, or CGI

File Handling

When do we care?


When you need to save some kind of information permanently
(like a counter)
When you want to modify a page on the fly (like a guestbook or chat.)

Opening a file


The open statement allows you to open a file on the server.
This file should be in your file areas, with 777 (!) permission.
(Obviously, this entails some risk. Your file could be modified by others by hand.)
General syntax:
open (HANDLENAME, "filename");
HANDLENAME is what you will call the file within the program
By tradition, HANDLENAME is all in uppercase
filename is the name of the file as it is found on your system.
You can later refer to it as <HANDLENAME>
It is basically thought of as an array separated by newlines.
It is polite to close a file as soon as possible
Close with the close command below

Opening for input


The open statement is modified based on what you want to do with the file
The standard open statement, open (HANDLENAME, "filename"); opens the file for INPUT.
This means that stuff will come in from the file to the program.
When you open a file in this way, you will probably be reading from it.
A very simple input program might look like this:

open (FRUITFILE, "fruit.txt");

while( $line = <FRUITFILE>){
if ($line =~ m/banana/){
print $line;
}; # end if
}; # end while
close FRUITFILE;

This code would open up the file called "fruit.txt" in the current directory of the SERVER
It would assign that file to the handle FRUITFILE
The next line would set up a loop putting the next line in the variable $line
Note that it is NOT an == equality check. The condition is actually an assignment.
It could be read like this. While (copy the next value from <FRUITFILE> to $line) works, do…
The if statement checks to see if the word "banana" is in the line
If it is, the line is printed out.
The if and while structures are closed, then the file is closed

Opening for output


Opening a file for standard output creates a new file if it does not already exist.
If the file does exist, it is overwritten. THIS CAN BE VERY IMPORTANT!!
A special version of the print statement sends stuff out to the file
The open file for output looks like this:
open (FRUITFILE, ">fruit.txt");
note that the > is pointing to the file from the handle. This indicates that information is flowing out from the program to the file.
To print to a file once it has been opened, simply say
print FRUITFILE value_to_print;
FRUITFILE must be a file opened for output or append (see below)
value_to_print could be a string value or a variable (or a combination)

Open for output is used to create a new file or to write over an existing file.
It is NOT usually used when we want to add new stuff to the end of a file.
See append below for that…

INPUT / OUTPUT EXAMPLE.



#!usr/local/bin/perl

#Opens up the fruit.txt file for input.
#grabs values from the file,
#replaces value "orange" with "grapefruit"
#places new value in a temporary variable
#closes fruit.txt
#opens fruit.txt for output
#writes the temporary variable to the file
#closes fruit.txt

#By Andy Harris, 2/17/97

#initialize $temp as empty

$temp = "";

#open up fruit.txt for input
open (OLDFRUIT, "fruit.txt");

#as long as there are values in OLDFRUIT…
while ($line = <OLDFRUIT>){
#do the substitution
$line =~ s/orange/grapefruit/g;
#add $line to $temp
$temp .=$line;
}; # end while

#close it up
close (OLDFRUIT);

#open up fruit.txt again, this time for output
open (NEWFRUIT, ">fruit.txt");

#write the value of $temp to NEWFRUIT
print NEWFRUIT $temp;

#close up NEWFRUIT
close (NEWFRUIT);

Open for Append


Works very much like open for output, except…
Old data is retained.
Any new values are written to the end of the file
Syntax:
open (HANDLENAME, ">>filename");
Note that this looks like open for output, but there are TWO arrows to the filename.
This is most useful when we want to add stuff to an existing file.
Often, we may want to add the results of a form entry to the end of an HTML page.

The following code might do that:


#!/usr/local/bin/perl

#guestbook.cgi
#by Andy Harris, 2/17/97

#load up the cgi library
require "cgi-lib.pl";

#get values from form, place them in array called input
&ReadParse (*input);

# in this case, we will assume that our form had textboxes named
# txtName, txtEmail, and txtMessage. We will place the values
# of these fields into plain old variables for ease of use.

$userName = $input("txtName");
$userEmail = $input("txtEmail");
$message = $input("txtMessage");

#open up the file called "guestbook.html" for append
open (GBOOK, ">>guestbook.html");

#Add the values from the variables to the guestbook
print GBOOK 'The user's name was: $userName <br>\n' ;
print GBOOK "Email address: " + $userEmail + "<br>\n";
print GBOOK "Message:" + $message + "<hr>\n";

#close up the html file
close (GBOOK);

Look at the guestbook on Andy's page for an example that does this with a pattern match!! (whoo hoo!)

Locating and using a perl script


Locating a suitable script is the easy part. See the end of the documentation for some
places to start.

Modification


Almost all scripts need to be modified in some way before they will run on our
system
Most programs you get from the net will have good documentation on which
variables to change and how to change them.
Copy the source code to your cgi-bin subdirectory
Give your program executable permission (711)
Often there will be a related html file. Copy it to the appropriate subdirectory as
well
(Probably public_html)
Change the first line so it points to klingon's copy of perl.
This line MUST read the following:
#!/usr/local/bin/perl
Look through the perl source code in your editor.
Look for comments that explain variables you need to change
If in doubt, leave it alone. Change only what you HAVE to at first.
The html document that refers to this script will require some changes as well.
Make sure that wherever it refers to the script (most likely in the action attribute of
the form) it has the correct URL for the script. Use the sample provided above,
replacing aharris with your userid and foo.pl with the name of your script.
Test, test, test!

Your assignment

Part one


Find and modify an email script so it will work on Klingon.
Change the form program you created back in the forms unit so it sends information to the email script.
Set your script to send info back to you.
When you have succeeded, forward the email from your page to me.

Part two


Use the ideas in this unit to create a perl script of your own device…

Possible scripts:


A guest book
A "chat" program
A quiz grader (give a quiz on a web page and return score to user)
A password program
A simple database