CGI Example

Example Information Transfer

Provides a CGI form example. To understand what data is sent, consider the following CGI example form:

<FORM ACTION="/cgi-bin/join.pl" METHOD="POST">
<B>First Name: </B><INPUT TYPE=TEXT NAME="firstname">
<B>Last Name: </B><INPUT TYPE=TEXT NAME="lastname">
<B>Address1: </B><INPUT TYPE=TEXT NAME="addr1">
<B>Address2: </B><INPUT TYPE=TEXT NAME="addr2">
<B>City: </B><INPUT TYPE=TEXT NAME="city">
<B>State: </B><SELECT NAME="state" SIZE=0>
<OPTION VALUE="0">--
<OPTION VALUE="1">AL
<OPTION VALUE="2">AK
<OPTION VALUE="3">AR
<OPTION VALUE="4">AS
<OPTION VALUE="5">AZ
<OPTION VALUE="6">CA
<OPTION VALUE="7">CO
<OPTION VALUE="8">CT
<OPTION VALUE="9">DC
<OPTION VALUE="10">DE
<OPTION VALUE="11">FL
<OPTION VALUE="12">FM
<OPTION VALUE="13">GA
<OPTION VALUE="14">GU
<OPTION VALUE="15">HI
<OPTION VALUE="16">ID
<OPTION VALUE="17">IA
<OPTION VALUE="18">IL
<OPTION VALUE="19">IN
<OPTION VALUE="20">KS
<OPTION VALUE="21">KY
<OPTION VALUE="22">LA
<OPTION VALUE="23">MA
<OPTION VALUE="24">MD
<OPTION VALUE="25">ME
<OPTION VALUE="26">MH
<OPTION VALUE="27">MI
<OPTION VALUE="28">MN
<OPTION VALUE="29">MO
<OPTION VALUE="30">MP
<OPTION VALUE="31">MS
<OPTION VALUE="32">MT
<OPTION VALUE="33">NC
<OPTION VALUE="34">ND
<OPTION VALUE="35">NE
<OPTION VALUE="36">NH
<OPTION VALUE="37">NJ
<OPTION VALUE="38">NM
<OPTION VALUE="39">NV
<OPTION VALUE="40">NY
<OPTION VALUE="41">OH
<OPTION VALUE="42">OK
<OPTION VALUE="43">OR
<OPTION VALUE="44">PA
<OPTION VALUE="45">PR
<OPTION VALUE="46">PW
<OPTION VALUE="47">RI
<OPTION VALUE="48">SC
<OPTION VALUE="49">SD
<OPTION VALUE="50">TN
<OPTION VALUE="51">TX
<OPTION VALUE="52">UT
<OPTION VALUE="53">VA
<OPTION VALUE="54">VI
<OPTION VALUE="55">VT
<OPTION VALUE="56">WA
<OPTION VALUE="57">WI
<OPTION VALUE="58">WV
<OPTION VALUE="59">WY
</SELECT>
<B>Zip: </B><INPUT TYPE=TEXT NAME="zip" MAXLENGTH=10 SIZE=10>
<B>Area Code/Phone:</B><INPUT TYPE=TEXT NAME="code" MAXLENGTH=3 SIZE=3><INPUT TYPE=TEXT NAME="phone" MAXLENGTH=7 SIZE=7>
<B>E-mail: </B><INPUT TYPE=TEXT NAME="email">

<center>
<INPUT TYPE="Submit" NAME="Submit" VALUE="Submit"> <INPUT TYPE="RESET"
VALUE="Clear">
</center>
</PRE>

</FORM>




This form would be included in an HTML file and defines the following values:
firstname, lastname, addr1, addr2, city, state, zip, code, phone, and email. If the user enters the following:

Firstname:	Mark
Lastname:	Allen
Addr1:		1010 Technology Drive
Addr2:		Apt 2B
City:		Hollywood
State:		MD
Zip:		20110
Code:		301
Phone:	  	3735555
Email:		mallen@myisp.com

The following string is sent:

&firstname=Mark&lastname=Allen&addr1=1010 Technology Drive&Addr2=Apt 2B&city=Hollywood&state=24&zip=20110&code=301&phone=3735555&email=mallen@myisp.com

Please be aware that the state selected above which is 24 corresponds to MD in the form table. Therefore based on this information, your server side script program needs to read the data, parse it into useable form and place it in a data file. Also it should respond to the input with an acknowledgement of receipt. This is usually done by generating an HTML output, thanking the user for their input. The data is read from the standard input and the environment variable CONTENT_LENGTH is used to tell how much data there is, if the POST method was specified in the HTML file. It is read from the environment variable QUERY_STRING if the GET method is used.

Perl Code to get the Data

The following code, written in perl can be used on the server side to get the data from the user and write it to a file:

#!/usr/bin/perl
#******************************************************
# This script maintains a database of members joining the group. 
#******************************************************
$database_file = "/home/httpd/members/members.dat";
$quote = "\"";$ASCII_ten = pack("c", 10);
$ASCII_thirteen = pack("c", 13);
$space = " ";

# Format the Web data received and make sure
# it does not contain any server-side includes
%data_received = &Get_Data();  # Get_Data() is a procedure
&No_SSI(*data_received);

# Make sure all mandatory fields are full and
# truncate all strings to a maximum of 255 characters
# Also make sure no new-line characters.
foreach $key (keys(%data_received)) {
	 $data_received{$key} =~ s/$ASCII_ten//ge; 
	$data_received{$key} =~ s/$ASCII_thirteen/$space/ge;
}

open(DATABASE,">>$database_file") || die "Content-type: text/html\n\nCannot open database.";

# Normally lock the database file now since several submissions may be received at the same time.
# The value 2 sets a write lock on the file. 
# The lock is currently commented out due to system problems.
# flock(DATABASE, 2);

# each element in the %data_received array is written to the file one at a time, 
# They are each separated by commas abd surrounded by quotes

print DATABASE $quote . $data_received{"firstname"} . $quote . "," . 
	$quote . $data_received{"lastname"} . $quote . "," . 
	$quote . $data_received{"addr1"} . $quote . "," . 
	$quote . $data_received{"addr2"} . $quote . "," . 
	$quote . $data_received{"city"} . $quote . "," . 
	$quote . $data_received{"state"} . $quote . "," . 
	$quote . $data_received{"zip"} . $quote . "," . 
	$quote . $data_received{"code"} . $quote . "," . 
	$quote . $data_received{"phone"} . $quote . "," . 
	$quote . $data_received{"email"} . $quote . "\n"; 

# The value 8 removes all locks from the file
flock(DATABASE, 8);
close(DATABASE);
# Output success message
print "Content-type: text/html", "\n\n";        # MIME header.
print "<HTML>", "\n";
print "<HEAD>";
print "<TITLE>Thanks for joining</TITLE>", "\n";
print "<HEAD>", "\n";
print "<BODY>", "\n";

print "<CENTER><BR><H2>",$data_received{"firstname"}," thanks for joining.</H2></CENTER>n\n";
print "<CENTER><BR><BR><H3>Your IP address is $ENV{'REMOTE_ADDR'}.</H3></CENTER>\n";
print "<CENTER><BR><H3>Your login name is $ENV{'REMOTE_IDENT'}.</H3><CENTER>\n";
print "<CENTER><BR><H3>Your host name is $ENV{'REMOTE_HOST'}.</H3></CENTER>\n";
print "<CENTER><BR><H3>Your user name is $ENV{'REMOTE_USER'}.</H3></CENTER>\n";

print "</BODY>", "\n";
print "</HTML>", "\n";

sub Get_Data { 
	local (%user_data, $input_string, $nv_pair, 
		@nv_pairs, $name, $value); 

	# If the data was sent via POST, then it is available 
	# from standard input. Otherwise, the data is in the 
	# QUERY_STRING environment variable. 
	if ( $ENV{'REQUEST_METHOD'} eq "POST" )
        {
#               $len = $ENV{`CONTENT_LENGTH`};
		read(STDIN,$input_string,$ENV{'CONTENT_LENGTH'});
	} 
	else {
		$input_string = $ENV{'QUERY_STRING'}; 
	}
	
	# This line changes the + signs to spaces. 
	$input_string =~ s/\+/ /g;

	# This line places each name/value pair as a separate 
	# element in the name_value_pairs array. 
	@nv_pairs = split(/&/, $input_string); 
	# This code loops over each element in the name_value_pairs 
	# array, splits it on the = sign, and places the value 
	# into the user_data associative array with the name as the 
	# key.
	foreach $nv_pair (@nv_pairs) {
	       ($name, $value) = split(/=/, $nv_pair); 

		# These two lines decode the values from any URL
		# hexadecimal encoding. The first section searches for a 
		# hexadecimal number and the second part converts the 
		# hex number to decimal and returns the character 
		# equivalent. 
		$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge; 
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge; 

		# If the name/value pair had been given a value previously, 
		# such as when multiple items are being selected,  
		# separate the items with a ":".
		if (defined($user_data{$name})) {
			$user_data{$name} .= ":" . $value; } 
		else { 
			$user_data{$name} = $value; 
		} 
	} 
	return %user_data;
}

sub No_SSI {
	 local (*data) = @_;
	 foreach $key (sort keys(%data)) { 
		$data{$key} =~ s/<!--(.|\n)*-->//g; 
	}
}

In the procedure "GetData()" this program checks the "REQUEST_METHOD" environment variable to determine what method for sending the data was used then gets the data from the appropriate environment variable, STDIN or QUERY_STRING.