Lecture Notes Seven: Building a CGI Processor (Part I).
Here's how HTTP works.

tucotuco.cs.indiana.edu% telnet burrowww.cs.indiana.edu 31090
Trying 129.79.245.98...
Connected to burrowww.cs.indiana.edu.
Escape character is '^]'.
GET /index.html HTTP1.1

HTTP/1.1 200 OK
Date: Tue, 18 Sep 2001 21:16:13 GMT
Server: Apache/1.3.20 (Unix)
Last-Modified: Thu, 13 Sep 2001 15:03:55 GMT
ETag: "74efb-2fe-3ba0cadb"
Accept-Ranges: bytes
Content-Length: 766
Connection: close
Content-Type: text/html

<html>

<head><title> Title </title> </head>

<body bgcolor=white>

<img src="wtc.jpg" align=right>

<p> This is the demo server. Here's 
a <a href="protected">link</a> to the demo <code>protected</code> 
directory on this server. As shown in class on Tuesday you can get 
in with the following combination of username and password: </p> 

<ul>

<li> <code>mjordan</code> <font color="lightgrey">(username)</font>

<li> <code>nba</code> <font color="lightgrey">(password)</font>

</ul>

<p> The instructors should also be able to get into the directory using
the instructor username and password. </p> 

<p> Here now are my sample assignments. </p> 

<ol>

<li> <a href="One.html">Homework One</a>

<li> <a href="Two.html">Homework Two</a>

</ol> 

</body>

</html>
Connection closed by foreign host.
tucotuco.cs.indiana.edu% 
Notice how little you type.

That's what goes on when you click here, too.

Notice that the server takes care of the MIME type.

For a script, the script is in charge of that.

Let's review some of the Perl needed for part two of assignment two.

How would you write this?

I'll let you think about it.

I'll build two Perl programs and you tell me which is closer to the one above.

Version One:

#!/usr/bin/perl

print "Calc> "; 

$line = <STDIN>; 
$count = 0; 

while (! ($line =~ /^bye$/i)) {
  if ($line =~ /^add/i) {
    $count += 1; 
    print "Your call has number: ", $count, "\n"; 
  }
  print "Calc> "; 
  $line = <STDIN>;    
}
Here's how it works:

burrowww.cs.indiana.edu% ./one
Calc> add
Your call has number: 1
Calc> add
Your call has number: 2
Calc> add
Your call has number: 3
Calc> add
Your call has number: 4
Calc> bye
burrowww.cs.indiana.edu% 
Version Two:
#!/usr/bin/perl

$param = $ARGV[0];

($name, $value) = split(/=/, $param); 

if ($name eq "arg") {
  $arg = $value + 1; 
  print "Your call has number: ", $arg, "\n"; 
  print "Note: please call with (./two arg=", $arg, ") next time.\n"; 
}
Here's how this runs.

burrowww.cs.indiana.edu% ./two
burrowww.cs.indiana.edu% ./two arg=0
Your call has number: 1
Note: please call with (./two arg=1) next time.
burrowww.cs.indiana.edu% ./two arg=1
Your call has number: 2
Note: please call with (./two arg=2) next time.
burrowww.cs.indiana.edu% ./two arg=2
Your call has number: 3
Note: please call with (./two arg=3) next time.
burrowww.cs.indiana.edu%
Well, which one is closer?

Actually, the second one.

The reason is: HTTP is connectionless.

That is, it has no recollection of who you are.

Here's how you might start the script discussed above.

#!/usr/bin/perl

&printTop;

$me = $ENV{SCRIPT_NAME}; 

$value = $ENV{QUERY_STRING}; 

$num = $value + 1; ; 

print qq{ 

  Your call has number: <font size=+5>$num</font> <p> 

  <a href="$me?$num">Click here</a> for more. <p> 

};

&printBottom; 

sub printTop {
  print "Content-type: text/html\n\n"; 
  print "<html><head><title>Some title</title></head><body bgcolor=\"white\">";
}

sub printBottom {
  print "</body></html>"; 
}
Next we will discuss the various form elements, for example:

To display: Use: Attributes:
A form <form>
... HTML form info
</form>
method
action
enctype
Single-line text field
<input type=text>
name
value
maxlength
size
Single-line password field
<input type=password>
name
value
maxlength
size
Multiple-line text area
<textarea></textarea>
name
cols
rows
wrap
Checkbox
<input type=checkbox>
name
value
checked
Radio buttons
<input type=radio>
name
value
checked
List of choices <select>
items in list...
</select>
name
multiple
size
Items in a <select> list <option>
value
selected
Clickable image
<input type=image>
name
align
src
File upload
<input type=file>
name
accept
Hidden field
<input type=hidden>
name
value
Reset button
<input type=reset>
value
Submit button
<input type=submit>
name
value

Then we will finally look at pattern matching.

We're using the =~ operator, together with the letter s on its right hand side, followed by a slash delimited pattern to be matched, and a string. When the pattern matches the string that follows the second slash will replace it. There are several rules and exceptions and we will summarize those that we care for here, through a couple of examples.

The dot (.) matches any one character except newline.

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
$a = "1234567890"; 
$a =~ s/./a/; 
print $a; 
frilled.cs.indiana.edu%./alpha
a234567890frilled.cs.indiana.edu%
To have the substitution happen everywhere it can happen, use g (global) aftre the third slash.

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
$a = "1234567890"; 
$a =~ s/./a/g; 
print $a; 
frilled.cs.indiana.edu%./alpha
aaaaaaaaaafrilled.cs.indiana.edu%
The pattern can be bigger (or longer):
frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
$a = "1234567890"; 
$a =~ s/../a/g; 
print $a; 
frilled.cs.indiana.edu%./alpha
aaaaafrilled.cs.indiana.edu%
Parentheses can be used as memory elements:

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
$a = "1234567890"; 
$a =~ s/(.)(.)/$2$1/g; 
print $a; 
frilled.cs.indiana.edu%./alpha
2143658709frilled.cs.indiana.edu%
And they can include larger patterns:
frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
$a = "1234567890"; 
$a =~ s/(..)/$1+1/g; 
print $a; 
frilled.cs.indiana.edu%./alpha
12+134+156+178+190+1frilled.cs.indiana.edu%
To have the part between the last two slashes act as Perl code use e (evaluate) after the third slash.

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
$a = "1234567890"; 
$a =~ s/(..)/$1+1/ge; 
print $a; 
frilled.cs.indiana.edu%./alpha
1335577991frilled.cs.indiana.edu%
Miscellaneous

A few other things needed in ReadParse (for Thursday) are listed below.

Characters have (decimal) ASCII codes that can be obtain with ord.

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
@values = ('A', 'B', 'C', 'D', 'E'); 
foreach $value (@values) {
  print $value, " has ASCII code: ", ord($value), "\n"; 
} 
frilled.cs.indiana.edu%./alpha
A has ASCII code: 65
B has ASCII code: 66
C has ASCII code: 67
D has ASCII code: 68
E has ASCII code: 69
frilled.cs.indiana.edu%
ASCII codes can be turned into characters with chr.

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
@values = (65, 66, 67, 68, 69); 
foreach $value (@values) {
  print "ASCII code $value stands for: ", chr($value), "\n"; 
} 
frilled.cs.indiana.edu%./alpha
ASCII code 65 stands for: A
ASCII code 66 stands for: B
ASCII code 67 stands for: C
ASCII code 68 stands for: D
ASCII code 69 stands for: E
frilled.cs.indiana.edu%
The hex function turns a hexadecimal value in a decimal one.

frilled.cs.indiana.edu%cat alpha
#!/usr/bin/perl
@values = (1, 10, 20, 100, 110, 111); 
foreach $value (@values) {
  print "$value in base 16 is equal to ", hex($value), " in base 10.\n"; 
} 
frilled.cs.indiana.edu%./alpha
1 in base 16 is equal to 1 in base 10.
10 in base 16 is equal to 16 in base 10.
20 in base 16 is equal to 32 in base 10.
100 in base 16 is equal to 256 in base 10.
110 in base 16 is equal to 272 in base 10.
111 in base 16 is equal to 273 in base 10.
frilled.cs.indiana.edu%
We now want to build a generic CGI processor.

We also need to come up with a definition of CGI.

(The lab this week will essentially by an introduction to mySQL).


Last updated: Sep 18, 2001 by Adrian German for A348/A548