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