_CGI AND THE WORLD WIDE WEB_ by G. Dinesh Dutt Listing One

Illustration Form

This form is used as a illustration to the article on CGI.


Title
  1. Author
  2. Title.

Submit Button
Reset Button.

Listing Two ############################################################################### ## CGI-PARSE.PL ## ## A library to read and parse the input available from forms as per the ## ## CGI 1.1 specification. ## ## This code is in the public domain for people to do whatever they wish to ## ## with it. But, maintain this copyright notice and don't say you wrote it. ## ## This work is distributed in the hope that its useful. But, the author is ## ## not liable for any any incurred damages, directly or indirectly due to ## ## the use or inability to use this software. ## ############################################################################### ############################################################################### ## CGIGetInput ## ## This is a small function which decodes the forms input. It looks at the ## ## REQUEST_METHOD environment variable to decide where to get the input from.## ## The user can invoke this subroutine thus : ## ## &CGIGetInput (*cgi_in); ## ## and the input is returned in an associative array called cgi_in, with the ## ## key being the name of field and its value being the value of the field ## ## as supplied by user. If the field does not have any input, the entry in ## ## the associative array will be undefined. ## ############################################################################### sub CGIGetInput { local (*input) = @_; local ($buffer,@nv_pairs); if ($ENV{'REQUEST_METHOD'} eq "GET") { $buffer = $ENV{'QUERY_STRING'}; } elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { return -1; } @nv_pairs = split (/\&/,$buffer); foreach $nvp (0..$#nv_pairs) { $nv_pairs[$nvp] =~ tr/+/ /; ($key, $keyword) = split (/=/, $nv_pairs[$nvp], 2); $key =~ s#%(..)#pack("c",hex($1))#ge; $keyword =~ s#%(..)#pack("c",hex($1))#ge; $input{$key} .= '\0' if (defined ($input{$key})); $input{$key} .= $keyword; } return 1; } ############################################################################### ## &PrintHeader (type/URL, is_it_a_URL) ## ## This function prints the default header. If a type is specified, that is ## ## printed, else the default text/html is printed. If the second parameter is## ## 1, then the Location header is printed instead of the text/html header. ## ## ## ## Example invocations : ## ## &PrintHeader ("text/plain", 0) ## ## &PrintHeader ("http://www.halcyon.com/hedlund/cgi-faq/",1) ## ## &PrintHeader ("",0) ## ############################################################################### sub PrintHeader { local ($toprint, $url_p) = @_; if ($toprint eq "") { print "Content-type: text/html\n\n"; } elsif ($url_p) { print "Location: $toprint\n\n"; } else { print "Content-type: $toprint\n\n"; } } 1; Listing Three ############################################################################### ## DEBUGCGI.PL ## ## This is a simple script which sets up a test environment for CGI script ## ## to be executed and then traps the common errors. The PATH is set to the ## ## minimal set by most systems, for example. All error messages are trapped ## ## and made available to the user. ## ## ## ## This code is in the public domain for people to do whatever they wish to ## ## with it. But, maintain this copyright notice and don't say you wrote it. ## ## This work is distributed in the hope that its useful. But, the author is ## ## not liable for any any incurred damages, directly or indirectly due to ## ## the use or inability to use this software. ## ############################################################################### $tmpdir = "/tmp/"; # The directory under which the error file will # be created. require "cgi-parse.pl"; %cgi_input = (); &CGIGetInput(*cgi_input); $script = $cgi_input{'DebugCgi-ScriptName'}; $method = $cgi_input{'DebugCgi-Method'}; $cmdargs = $cgi_input {'DebugCgi-CmdArgs'}; delete ($cgi_input {'DebugCgi-ScriptName'}); delete ($cgi_input {'DebugCgi-Method'}); delete ($cgi_input {'DebugCgi-CmdArgs'}); $inp = ""; foreach $elem (keys %cgi_input) { $cgi_input{$elem} = $cgi_input{$elem}; $cgi_input{$elem} =~ s# #+#g; $cgi_input{$elem} =~ s#([^+A-Za-z0-9])#sprintf("%%%02x",ord($1))#ge; $cgi_input{$elem} =~ s#%3d#=#g; $inp .= "$elem=$cgi_input{$elem}&"; } # Encode the input in the form used by HTTP. #Turn off the include path. The script must use its own @INC and environment. if (! -e $script) { &PrintErrHeader; print "Script $script does not exist
"; &PrintErrTrailer; exit (2); } if (! -r $script && ! -x $script) { &PrintErrHeader; print "Script $script is not readable/executable by server
"; &PrintErrTrailer; exit (2); } #Set the request method. $error_file = $tmpdir.$^T; $ENV{'REQUEST_METHOD'} = $method; if ($method eq "GET") { $ENV{'QUERY_STRING'} = $inp; open (OUTPUT, "$script $cmdargs 2\>/tmp/errors |") || &cry ("unable to pipe script $! \n"); } elsif ($method eq "POST") { $ENV{'CONTENT_LENGTH'} = length($inp); open (OUTPUT, "echo \"$inp\" | $script $cmdargs 2>$error_file |") || &cry ("unable to pipe script $! \n"); } else { &PrintHeader; print "Unknown method: $method\n"; exit (3); } $_ = ; if (!/^Content-type: / && !/^Location: /) { if (-s $error_file) { open (ERRF, "< $error_file") || &cry ("testcgi.cgi - Unable to open error file $!\n"); &PrintHeader; print "\n"; @errors = ; &PrintErrHeader; print "Script $script has an execution error !!!

"; print "@errors \n"; &PrintErrTrailer; unlink ($error_file); exit (4); } &PrintErrHeader; print "The script $script has an error :

"; print "It does not output the Content-type/Location header.
"; print "Here's what it printed as the first line.\n"; print "
\n";
    print;
    print "
\n"; &PrintErrTrailer; exit (3); } $format = m#^Content-type:[ \t]*text/html#; $_ = ; if (!/^$/) { &PrintErrHeader; print "The script $script has an error :

"; print "The second line it outputs must be a blank, instead I got
\n";
    print;
    print "
"; &PrintErrTrailer; exit (3); } &PrintHeader; print "

Script $script seems OK !

\n"; print "

Here is its output:
\n"; print "

\n" if (!$format) ;
print $ENV{'PATH_INFO'},"\n";
while () {
    print;
}
print "
" if (!$format); print ""; exit (0); sub cry { local ($message) = @_; &PrintHeader; print "

Debugcgi Error !!

"; print "DebugCGI encountered an error during execution. The error is: ", $message; print "\n"; exit; } sub PrintErrHeader { &PrintHeader; print "

Script Error !!

"; } sub PrintErrTrailer { print "\n"; } Listing Four ############################################################################### ## TESTCGI.PL ## ## This is a script which sets up a test environment for the CGI script ## ## to be executed and then traps the common errors. The PATH is set to the ## ## minimal set by most systems, for example. All error messages are trapped ## ## and made available to the user. Thus, he does not have to wonder why for ## ## error cases. ## ## This code is in the public domain for people to do whatever they wish to ## ## with it. But, maintain this copyright notice and don't say you wrote it. ## ## This work is distributed in the hope that its useful. But, author is not ## ## liable for any any incurred damages, directly or indirectly due to use ## ## or inability to use this software. ## ############################################################################### $tmpdir = "/tmp/"; # Directory under which the error file will be created. require "cgi-parse.pl"; sub Usage { print "Usage: testcgi [-f filename containing input] -m METHOD scriptname\n"; print " where METHOD is GET/POST\n"; exit (0); } %cgi_input = (); &CGIGetInput(*cgi_input); &PrintHeader; $script = $cgi_input{'TestCgi-ScriptName'}; $method = $cgi_input{'TestCgi-Method'}; delete ($cgi_input {'TestCgi-ScriptName'}); delete ($cgi_input {'TestCgi-Method'}); $inp = ""; foreach $elem (keys %cgi_input) { $cgi_input{$elem} = $cgi_input{$elem}; $cgi_input{$elem} =~ s# #+#g; $cgi_input{$elem} =~ s#([^+A-Za-z0-9])#sprintf("%%%02x",ord($1))#ge; $cgi_input{$elem} =~ s#%3d#=#g; $inp .= "$elem=$cgi_input{$elem}&"; } # Encode the input in the form used by HTTP. #Turn off the include path. The script must use its own @INC and environment. @INC=(); $ENV{'PATH'} = "/bin:/usr/bin/:/etc:"; #Set the request method. $error_file = $tmpdir.$^T; $ENV{'REQUEST_METHOD'} = $method; if ($method eq "GET") { $ENV{'QUERY_STRING'} = $inp; open (OUTPUT,"$script 2\>/tmp/errors |") || die "unable to pipe script $! \n"; } elsif ($method eq "POST") { $ENV{'CONTENT_LENGTH'} = length($inp); open (OUTPUT,"echo \"$inp\" | $script 2>$error_file |") || die "unable to pipe script $! \n"; } else { print "Unknown method: $method\n"; exit (3); } print "\n"; $_ = ; if (!/^Content-type: / && !/^Location: /) { if (-s $error_file) { open (ERRF, "< $error_file") || die "testcgi.cgi - Unable to open error file $!\n"; print "\n"; @errors = ; print "

Script $script has an execution error !!!

\n"; print "@errors \n"; unlink ($error_file); exit (4); } print "

Script $script has an error !!!

\n"; print "It does not output the Content-type/Location header.\n"; exit (3); } $format = m#^Content-type:[ \t]*text/html#; $_ = ; if (!/^$/) { print "Your second line must be a blank\n"; exit (3); } print "

Script $script Seems OK

\n"; print "

Here is its output \n"; print "

\n" if (!$format) ; 
while () { 
    print; 
} 
print "
" if (!$format); print ""; exit (0); Listing Five

Test CGI Form

This form is used as a front-end to testcgi.


Script Name
Method

Submit Button
Reset Button.

Example 1: (a) if ($ENV{'REQUEST_METHOD'} eq "GET") { $input = $ENV{'QUERY_STRING'}; } (b) if ($ENV{'REQUEST_METHOD'} eq "POST") { if (!defined ($ENV{'CONTENT_LENGTH'})) { print "Error: CONTENT_LENGTH not set\n"; exit; } read (STDIN, $buffer, $ENV{'CONTENT_LENGTH}); } Example 2: # Using the cgi-parse.pl, &PrintHeader; # Print just the default text/html; &PrintHeader ("text/plain") # Print type to be text/plain. # Redirect request to get new document &PrintHeader ("http://amadeus.org/Mozarts_Life.html",1);