Perl CGI programming


What is CGI

CGI is currently maintained by NCSA, which defines CGI as follows:

CGI (Common Gateway Interface), a common gateway interface, is a program that runs on a server such as an HTTP server and provides an interface with client HTML pages.


Web browsing

To better understand how CGI works, we can click on a link or URL process on the web page:

  • 1, use your browser to access the URL and connect to the HTTP web server.
  • 2, the Web server receives the request information will resolve the URL, and find out whether the accessed file exists on the server, if there is the contents of the return file, otherwise the error message is returned.
  • 3. The browser receives information from the server and displays the received files or error messages.

CGI programs can be Python scripts, PERL scripts, SHELL scripts, C or C-programs, etc.


CGI architecture diagram

Perl CGI programming


Web server support and configuration

Before you program CGI, make sure that your Web server supports CGI and that CGI handlers are configured.

Apache supports CGI configurations:

Set up the CGI directory:

ScriptAlias /cgi-bin/ /var/www/cgi-bin/

All HTTP server execution CGI programs are stored in a pre-configured directory. This directory is called the CGI directory, and by convention it is named /var/www/cgi-bin directory.

The extension of the CGI file .cgi, and Perl can also use .pl extension.

By default, the Linux server configuration runs in the cgi-bin directory for /var/www.

If you want to specify other directories that run CGI scripts, you can modify the httpd.conf profile as follows:

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options +ExecCGI
   Order allow,deny
   Allow from all
</Directory>

Add the suffix .pl AddHandler so that we can access the perl script file .pl end of the file:

AddHandler cgi-script .cgi .pl .py

The first CGI program

Let's create a test .cgi file, as follows:

#!/usr/bin/perl

print "Content-type:text/html\r\n\r\n";
print '<html>';
print '<head>';
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print '</head>';
print '<body>';
print '<h2>Hello Word! </h2>';
print '<p>来自W3Cschool教程第一个 CGI 程序。</p>';
print '</body>';
print '</html>';

1;

Then open the browser and http://localhost/cgi-bin/test.cgi, and the output is as follows:

Perl CGI programming

The output of the first line of the script, "Content-type:text/html\n\n", is sent to the browser and the browser is informed that the type of content displayed is "text/html".


HTTP head

The test .cgi "Content-type:text/html" in the contents of the file, which is part of the HTTP header and is sent to the browser to tell the browser the type of content of the file.

The format of the HTTP header is as follows:

HTTP 字段名: 字段内容

For example:

Content-type:text/html\r\n\r\n

The following table describes the information that http heads are frequently used in CGI programs:

Head Describe
Content-type: The requested MIMI information corresponding to the entity. For example: Content-type:text/html
Expires: Date The date and time the response expired
Location: URL Used to redirect the receiver to a location where the URL is not requested to complete the request or identify a new resource
Last-modified: Date The last time the resource was requested to be modified
Content-length: N The length of the requested content
Set-Cookie: String Set http cookies

CGI environment variables

All CGI programs receive the following environmental variables, which play an important role in CGI programs:

The name of the variable Describe
CONTENT_TYPE The value of this environment variable indicates the TYPE type of information passed. At the moment, CONTENT_TYPE variables are generally: application/x-www-form-urlencoded, which says the data comes from HTML forms.
CONTENT_LENGTH If the server and CGI program information is passed in a POST, this environment variable is even the number of bytes of valid data that can be read from the standard input STDIN. This environment variable must be used when reading the data entered.
HTTP_COOKIE The contents of the COOKIE within the client.
HTTP_USER_AGENT Provides customer browser information that contains the number of versions or other proprietary data.
PATH_INFO The value of this environment variable represents other path information immediately after the CGI program name. It often appears as a parameter of the CGI program.
QUERY_STRING If the server and CGI program information is transmitted in a GET, the value of this environment variable even if the information is passed. T his information is followed by the name of the CGI program, and a question mark is used between the two. Separated.
REMOTE_ADDR The value of this environment variable is the IP address of the client sending the request, for example, 192.168.1.67 above. T his value is always present. And it is the unique identity that Web clients need to provide to Web servers, which can be used in CGI programs to distinguish between different Web clients.
REMOTE_HOST The value of this environment variable contains the host name of the client that sent the CGI request. If you do not support the query you want, you do not need to define this environment variable.
REQUEST_METHOD Provides the method to which the script is called. For scripts that use the HTTP/1.0 protocol, only GET and POST make sense.
SCRIPT_FILENAME The full path to the CGI script
SCRIPT_NAME The name of the CGI script
SERVER_NAME This is the host name, alias, or IP address of your WEB server.
SERVER_SOFTWARE The value of this environment variable contains the name and version number of the HTTP server that called the CGI program. For example, the above value is Apache/2.2.14 (Unix)

Here's a simple CGI script that outputs CGI's environment variables:

#!/usr/bin/perl

print "Content-type: text/html\n\n";
print '<meta charset="utf-8">';
print "<font size=+1>环境变量:</font>\n";
foreach (sort keys %ENV)
{
  print "<b>$_</b>: $ENV{$_}<br>\n";
}

1;

File download

If we want to download files through Perl CGI, we need to set a different header information, as follows:

#!/usr/bin/perl

# HTTP Header
print "Content-Type:application/octet-stream; name=\"FileName\"\r\n";
print "Content-Disposition: attachment; filename=\"FileName\"\r\n\n";

# Actual File Content will go hear.
open( FILE, "<FileName" );
while(read(FILE, $buffer, 100) )
{
   print("$buffer");
}

Use the GET method to transfer data

The GET method sends encoded user information to the service side, and the data information is included on the URL of the request page to "?" number split, as follows:

http://www.test.com/cgi-bin/test.cgi?key1=value1&key2=value2
Some other comments about get requests:
  • GET requests can be cached
  • Get requests remain in the browser history
  • GET requests can be bookmarked
  • GET requests should not be used when processing sensitive data
  • Get requests have a length limit
  • GET requests should only be used to get data back

Simple url example: GET method

Here's a simple URL that uses the GET method to send .cgi to the test program:

/cgi-bin/test.cgi?name=W3Cschool教程&url=http://www.w3cschool.cn

Here's the code .cgi the test file:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取文本信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "GET")
{
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$name = $FORM{name};
$url  = $FORM{url};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print "</head>";
print "<body>";
print "<h2>$name网址:$url</h2>";
print "</body>";
print "</html>";

1;

Check the browser and the output is as follows:

Perl CGI programming

Simple form example: GET method

The following is a form that uses THEML to send two datas to the server using the GET method, and the submitted server script is also a test.cgi file, the test .html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>W3Cschool教程(w3cschool.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="get">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>



Use the POST method to pass data

Using the POST method to pass data to the server is more secure and reliable, as sensitive information such as user passwords requires the use of POST to transfer data.

The following is also a test .cgi, which can also handle POST form data submitted by the browser:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取文本信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$name = $FORM{name};
$url  = $FORM{url};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print "</head>";
print "<body>";
print "<h2>$name网址:$url</h2>";
print "</body>";
print "</html>";

1;

The following is a form that uses THEML to send two datas to the server using the GET method, and the submitted server script is also a test.cgi file, the test .html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>W3Cschool教程(w3cschool.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>


Pass checkbox data through a CGI program

Checkbox is used to submit one or more option data, and the test .html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>W3Cschool教程(w3cschool.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="POST" target="_blank">
<input type="checkbox" name="youj" value="on" /> W3Cschool教程
<input type="checkbox" name="google" value="on" /> Google
<input type="submit" value="选择站点" />
</form>
</body>
</html>

Here's the code .cgi the test file:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
if( $FORM{youj} ){
   $youj_flag ="ON";
}else{
   $youj_flag ="OFF";
}
if( $FORM{google} ){
   $google_flag ="ON";
}else{
   $google_flag ="OFF";
}

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print "</head>";
print "<body>";
print "<h2> W3Cschool教程选中状态 : $youj_flag</h2>";
print "<h2> Google 选择状态 : $google_flag</h2>";
print "</body>";
print "</html>";

1;



Radio data is passed through the CGI program

Radio passes only one data to the server, and the test .html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>W3Cschool教程(w3cschool.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post" target="_blank">
<input type="radio" name="site" value="youj" /> W3Cschool教程
<input type="radio" name="site" value="google" /> Google
<input type="submit" value="提交" />
</form>
</body>
</html>

The .cgi script code is as follows:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$site = $FORM{site};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print "</head>";
print "<body>";
print "<h2> 选择的网站 $site</h2>";
print "</body>";
print "</html>";

1;



Textarea data is passed through the CGI program

Textarea passes multiple lines of data to the server, and the test .html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>W3Cschool教程(w3cschool.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4">
在这里输入内容...
</textarea>
<input type="submit" value="提交" />
</form>
</body>
</html>

The .cgi script code is as follows:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$text_content = $FORM{textcontent};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print "</head>";
print "<body>";
print "<h2>输入的文本内容为:$text_content</h2>";
print "</body>";
print "</html>";

1;



The pull-down data is passed through the CGI program

The HTML pull-down box code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>W3Cschool教程(w3cschool.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post" target="_blank">
<select name="dropdown">
<option value="youj" selected>W3Cschool教程</option>
<option value="google">Google</option>
</select>
<input type="submit" value="提交"/>
</form>
</body>
</html>

The .cgi script code looks like this:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$site = $FORM{dropdown};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>W3Cschool教程(w3cschool.cn)</title>';
print "</head>";
print "<body>";
print "<h2>选择的网站是:$site</h2>";
print "</body>";
print "</html>";

1;



Cookies are used in CGI

One of the great disadvantages of the http protocol is that the user's identity is not judged, which is a great inconvenience to the programmer, and the emergence of cookie functions to make up for this deficiency.

Cookies are when the customer accesses the script, through the customer's browser, writes the record data on the customer's hard drive, and when the customer accesses the script the next time the data information is taken back, thus achieving the function of identity identification, cookies are often used in identity verification.

The syntax of cookies

The http cookie is sent through the http head, which is delivered earlier than the file, and the syntax of the head set-cookie is as follows:

Set-cookie:name=name;expires=date;path=path;domain=domain;secure 
  • name-name: the value of the cookie needs to be set (name cannot be ; "and" , "number" when there are multiple name values used " ; " Separation, e.g. name1=name1; n ame2=name2; n ame3=name3
  • expires=date: the expiration date of the cookie, format: expires="Wdy, DD-Mon-YYYYY HH:MM:SS"
  • path: Set the path supported by the cookie, if path is a path, then the cookie takes effect on all files and subdirectts in this directory, e.g.: path is "/cgi-bin/" and if path is a file, the cookie means effective for that file, e.g., path=/cgi bin/cookie.cgi".
  • domain-domain: Domain name effective for cookies, e.g.: domain-"www.w3cschool.cn"
  • Secure: If this flag is given, the cookie can only be passed through the https server of the SSL protocol.
  • The receipt of cookies is achieved by HTTP_COOKIE environment variable, which the CGI program can retrieve to obtain cookie information.

Cookie settings

Cookies are set up very simply and are sent separately at the http header. The following examples have UserID, Password, and expires set in cookies:

#!/usr/bin/perl

print "Set-Cookie:UserID=XYZ;\n";
print "Set-Cookie:Password=XYZ123;\n";
print "Set-Cookie:Expires=Tuesday, 31-Dec-2017 23:12:40 GMT";\n";
print "Set-Cookie:Domain=www.w3cschool.cn;\n";
print "Set-Cookie:Path=/perl;\n";
print "Content-type:text/html\r\n\r\n";
...........其他 HTML 内容

Find cookies

The cookie information retrieval page is very simple, and the cookie information is stored in CGI's HTTP_COOKIE variables, in the following format:

#!/usr/bin/perl
$rcvd_cookies = $ENV{'HTTP_COOKIE'};
@cookies = split /;/, $rcvd_cookies;
foreach $cookie ( @cookies ){
   ($key, $val) = split(/=/, $cookie); # splits on the first =.
   $key =~ s/^\s+//;
   $val =~ s/^\s+//;
   $key =~ s/\s+$//;
   $val =~ s/\s+$//;
   if( $key eq "UserID" ){
      $user_id = $val;
   }elsif($key eq "Password"){
      $password = $val;
   }
}
print "User ID  = $user_id\n";
print "Password = $password\n";

The output of the above examples is:

User ID = XYZ
Password = XYZ123

CGI module

Perl offers a number of built-in CGI modules, often available in the following two: