CGI is shorter for ‘Common Gateway Interface’. CGI is component running on web servers 
and acts as an interface to database, documents and other applications. It receives 
requests from users (web browsers), performs tasks and returns the result back to the user.

CGI can be written in many programming languages. Most widely used and most suitable 
language for writing cgi scripts is Perl. Most UNIX based systems support it. 
CGI invokes .cgi script, which calls the program in which it was written and interprets 
the code.

Since HTML is used for representation of data in web browsers only, CGI might be the next 
step, because it enables more interactions between end user and web server. CGI is needed 
to create guest books, counters, forms and interactive charts within your web page.




Get started

For beginning let’s make an example how CGI and Perl are involved in the process of HTTP request.

CGI script is nothing more than ordinary text file. This is first exmple:

#! /usr/bin/perl

use CGI qw(:standard);
print header;
print "Hello World";


First line tells the interpreter which program will be used for execution - perl. 
Next line imports CGI’s standard library, which holds some useful functions. 
‘print’ functions are used to display data in web browser.

Copy the text above in file first.cgi and upload the file to your web server in 
/cgi-bin/mycgi/ directory. CGI scripts must have its file permissions set to 755 
(or at least all users should have execute privileges).

Script can be easiliy started from your web browser:
http://www.yourdomain.com/cgi-bin/mycgi/first.cgi

Click here to execute my first.cgi script.

New window should appear saying ‘Hello world’ if cgi script was compiled and 
executed correctly.
Setting up CGI environment is out of scope of this tutorial, if you need help call 
your server administrator.



When sending response back to user, CGI script creates html response with all 
necessary tags. Another example:

#!/usr/bin/perl -wT
print "Content-type: text/html\n\n";
print "<html><head><title>Hello World</title></head>\n";
print "<body>\n";
print "<h2>Hello, world!</h2>\n";
print "</body></html>\n";




Into Perl

This section covers basics of Perl: declaring variables, arrays, hashtables and some basic operations upon them.

Remember that cgi scripts should always start with:
#! /usr/bin/perl -wT

use CGI qw(:standard);
print header;



Strings

Declaring and using strings:
my $string = 'dummy string';
print "some $string\n";

my $stringLength = length($string);
print “String: $string has length: $stringLength\n”;


Join strings together:
my $S1 = 'string';
my $S2 = ' is ';
my $S3 = 'long';
print “$S1.S2.$S3\n";


Directly insert piece of html code into document:
print <<TEXT_TO_PRINT;
This is my text. Send me yours if you want.<p>
<a href="mailto:name@somewhere.com">send me an email!</a></p>
TEXT_TO_PRINT



Integers

Declaring and using integers:
my $int1 = 1;
my $int2 = 2;
my $sum = $int1 + $int2;
$sum++;
print $sum;



Arrays

Declaring and using arrays:
my @colors = ("red", "green", "blue");
print $colors[0]."\n";
print $colors[1]."\n";
print $colors[2]."\n";

push(@ colors, 'cyan');
push(@ colors, ('black', 'white'));

my $numberOfColors = scalar(@ colors);
print "array of colors contains $numberOfColors elements";


Iterating over array:
foreach my $i (@ colors) {
	print "$i\n";
}

# or

foreach my $i (0..$#colors) {
   print "color $i is $colors[$i]\n";
}


Get first element:
my $first = shift(@colors);


Get last element:
my $last = pop(@colors);
# or
my $last = $colors[$#colors];

where $#colors is equivalent to scalar(@colors)-1.


Slicing arrays:
my @slice = @colors[1..2];


Sort alphabetically:
my @sortedColors = sort(@colors);


Sorting numbers (alphabetically 12 is before 2, but not numerically):
my @numberList = (3, 1, 8, 5);
my @sortedNumberList = sort( {$a <=> $b;} @numberList);


Invert order of elements:
my @invertedColors = reverse(@colors);


Join elements into single string:
my $colorString = join(", ",@colors);
print $colorString;



Hashtables

Declaring and using hashtables:
my %hashTable;
$hashTable{'name1'} = 'John';
$hashTable{'name2'} = 'Frank';
$hashTable{'name3'} = 'Rachel';

print $hashTable{'name1'}."\n";

while (my($key, $value) = each(%hashTable))
{
     print $key.' - '.$value."\n";
}

if (exists $hashTable{1})
{
     print "name1 exists in hashtable";
}
else
{
     print "name1 does not exist in hashtable";
}


Adding items:
$hashTable{name4} = “Samuel”;


Get hashtable size:
my $hashTableSize = scalar keys(%hashTable);
print "hashtable size: ".$hashTableSize;


Delete entry:
delete $hashTable{key2};


Delete all entries:
%hashTable = ();



Loops

While loop:
my $integer = 0;
while($integer < 5)
{
     print $integer."\n";
     $integer++;
}


For loop (I see no output from this for loop ???):
for(my $c = 0; $c++; $c < 10)
{
     print $c."\n";
}


Iterators:
my @colors = ("red","green","blue");
foreach my $i (@colors) {
     print "$i\n";
}



Conditions

my $number = 99;
if($number eq 99)
{
     print 'number is exactly 99';
}
else
{
     print 'number is NOT 99';
}


if($number eq 99)
{
     print 'number is exactly 99';
}
elsif($number eq 100)
{
     print 'number is exactly 100';
}
else
{
     print 'number is NOT 99, NEITHER 100';
}


my $name = 'Matjaz';
if($name eq 'Matjaz')
{
     print 'You are the boss!';
}


unless($name eq 'matjaz')
{
     print 'What a freak...';
}



This is basically all you need to know about Perl for now. Now, let’s focus on CGI.



CGI is back

Environment variables is hashtable with keys and values which web server sends to CGI program.

DOCUMENT_ROOT     The root directory of your server
HTTP_COOKIE             The visitor's cookie, if one is set
HTTP_HOST                 The hostname of the page being attempted
HTTP_REFERER          The URL of the page that called your program
HTTP_USER_AGENT   The browser type of the visitor
HTTPS                           "on" if the program is being called through a secure server
PATH                             The system path your server is running under
QUERY_STRING          The query string (see GET, below)
REMOTE_ADDR           The IP address of the visitor
REMOTE_HOST           The hostname of the visitor (if your server has 
reverse-name-lookups on; otherwise this is the IP address again)
REMOTE_PORT           The port the visitor is connected to on the web server
REMOTE_USER           The visitor's username (for .htaccess-protected pages)
REQUEST_METHOD   GET or POST
REQUEST_URI             The interpreted pathname of the requested document or CGI 
(relative to the document root)
SCRIPT_FILENAME     The full pathname of the current CGI
SCRIPT_NAME             The interpreted pathname of the current CGI (relative to the 
document root)
SERVER_ADMIN          The email address for your server's webmaster
SERVER_NAME           Your server's fully qualified domain name
SERVER_PORT           The port number your server is listening on
SERVER_SOFTWARE   The server software you're using (e.g. Apache 1.3)


This is example of script, which prints all environment variables:

#!/usr/bin/perl -wT

use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

print header;
print start_html("Environment");

foreach my $key (sort(keys(%ENV))) {
    print "$key = $ENV{$key}<br>\n";
}

print end_html;


Here are my environment variables.




GET function

To send user data to server, you can use two methods: GET and POST. The values which 
are sent can be filled in a form. Paste the following html code to your web page:


<form action="someScript.cgi" method="GET">  
ID: <input type="text" name="id" size=30><p>
Name:  <input type="text" name="name" size=30><p>
<input type="submit">
</form>


With GET function, the input values are sent as part of url address like this:

http://www.matjazcerkvenik.si/cgi-bin/someScript.cgi?id=123&name=John

Two parameters are sent to CGI program: id and name. The parameters are sent in 
QUERY_STRING environment variable.


Get single parameter from QUERY_STRING:

my $id = param('id');
my $name = param('name');


Get all parameters at once (array):

my @fieldnames = param();

Because all parameters are sent as part of the url, GET method is definitely not the 
safest one. It is strongly recomended that sensitive data (passwords, user IDs...) 
is not sent in url. In such cases it is better to use POST method. All you need to do 
is modify method (from GET to POST) inside html form. The rest is done by CGI.pm library.




Guestbook example

Paste the following html form in one of your pages:

<form action="http://www.matjazcerkvenik.si/cgi-bin/mycgi/guestList.cgi"
    method="POST">
Name: <input type="text" name="name"> <br>
E-mail: <input type="text" name="email"> <br>
Comment: <textarea name="comment" cols=35 rows=4>Are you moonwalker?
    </textarea> <br>
<input type="submit" value="Submit">
</form>



Make a Perl script that reads all text fields from the form, and reads two environment 
variables: remote address and type of web browser. Then store this data into file.

#! /usr/bin/perl

use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
use strict;
print header;

open(FILEHANDLE, ">>./guestList.txt") || die('cannot open file: '.$!);

my $name = param('name');
my $email = param('email');
my $comment = param('comment');
my $hostname = $ENV{REMOTE_ADDR};
my $browser = $ENV{HTTP_USER_AGENT};

print FILEHANDLE "Name: $name\nEmail: $email\nHostname: $hostname\nBrowser: $browser\nComment: $comment\n--------------------------------------------\n";
close(FILEHANDLE);

print start_html("Guest List");

print "Pozdravljen $name <br><br>";
print "<a href=\"http://www.matjazcerkvenik.si\">home</a>";

print end_html;