Perl CGI Programming



What is CGI

CGI is currently maintained by NCSA. NCSA defines CGI as follows:

CGI (Common Gateway Interface), common gateway interface, it is a program , runs on the server such as: HTTP server, providing an interface with the client HTML page.


Web browsing

In order to better understand how CGI works, we can start with the process of clicking a link or URL on a web page:

  • 1. Use your browser to access the URL and connect to the HTTP web server.

  • 2. After receiving the request information, the web server will parse the URL and check whether the accessed file exists on the server. If the file exists, it will return the content of the file, otherwise it will return an error message.

  • 3. The browser receives information from the server and displays the received file or error message.

CGI program can be a Python script, PERL script, SHELL script, C or C++ program, etc.


CGI architecture diagram

cgiarch


Web server support and configuration

Before you perform CGI programming, make sure you The web server supports CGI and has CGI handlers configured.

Apache supports CGI configuration:

Set the CGI directory:

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

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

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

By default, the cgi-bin directory where the Linux server is configured to run is /var/www.

If you want to specify other directories for running CGI scripts, you can modify the httpd.conf configuration file as follows:

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

Add the .pl suffix in AddHandler so that we can access it. Perl script file ending with pl:

AddHandler cgi-script .cgi .pl .py

The first CGI program

Below we create a test.cgi file, the code is 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>php中文网(php.cn)</title>';
print '</head>';
print '<body>';
print '<h2>Hello Word! </h2>';
print '<p>来自php中文网第一个 CGI 程序。</p>';
print '</body>';
print '</html>';

1;

Then through the browser Open http://localhost/cgi-bin/test.cgi, the output result is as follows:

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


HTTP header

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

The format of the HTTP header is as follows:

HTTP 字段名: 字段内容

For example:

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

The following table introduces the information commonly used in HTTP headers in CGI programs:

HeaderDescription
Content-type:The requested MIME information corresponding to the entity . For example: Content-type:text/html
Expires: DateThe date and time the response expires
Location: URL is used to redirect the recipient to a non-requested URL to complete the request or identify a new resource
Last-modified: Date The last modification time of the requested resource
Content-length: NThe requested content length
Set-Cookie: String Set Http Cookie

CGI Environment Variables

All CGI programs receive the following environment variables, which are Plays an important role in CGI programs:

##Variable nameDescription##CONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_USER_AGENTPATH_INFOQUERY_STRINGREMOTE_ADDRREMOTE_HOSTREQUEST_METHODSCRIPT_FILENAMESCRIPT_NAMESERVER_NAMESERVER_SOFTWARE

The following is a simple CGI script that outputs CGI 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 implement file download through Perl CGI, we need to set different headers Information, as shown below:

#!/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 transmit data

The GET method sends the encoded user information to the server. The data information is included in the URL of the request page, to "?" separated, as follows:

http://www.test.com/cgi-bin/test.cgi?key1=value1&key2=value2
Some other notes about GET requests:
  • GET requests can be cached

  • GET requests Remain in browser history

  • GET requests can be bookmarked

  • GET requests should not be used when handling sensitive data

  • GET requests have length limits

  • GET requests should only be used to retrieve data

Simple URL example: GET method

The following is a simple URL, using the GET method to send two parameters to the test.cgi program:

/cgi-bin/test.cgi?name=php中文网&url=http://www.php.cn

The following is the code of the test.cgi 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())/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>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>$name网址:$url</h2>";
print "</body>";
print "</html>";

1;

Check the browser, the output result is as follows:

Simple form example: GET method

The following is a form using the GET method through HTML Send two data to the server. The submitted server script is also the test.cgi file. The test.html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.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>

In the browser, the execution effect is as follows:


Use the POST method to transfer data

Using the POST method to transfer data to the server is more secure and reliable. Some sensitive information such as user passwords need to use POST to transfer data.

The following is also test.cgi, which can also process 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())/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>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>$name网址:$url</h2>";
print "</body>";
print "</html>";

1;

The following is a form through HTML that uses the GET method to send two data to the server, submit The server script is also the test.cgi file, and the test.html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.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>

In the browser, the execution effect is as follows:

Through CGI The program passes checkbox data

checkbox is used to submit one or more option data. The test.html code is as follows:

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

The following is the code of the test.cgi 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())/eg;
   $FORM{$name} = $value;
}
if( $FORM{php} ){
   $php_flag ="ON";
}else{
   $php_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>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2> php中文网选中状态 : $php_flag</h2>";
print "<h2> Google 选择状态 : $google_flag</h2>";
print "</body>";
print "</html>";

1;

In the browser, the execution effect is as follows:


Transfer Radio data through CGI program

Radio only sends it to the server Pass a data, the test.html code is as follows:

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

test.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())/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>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2> 选择的网站 $site</h2>";
print "</body>";
print "</html>";

1;

In the browser, the execution effect is as follows:


Transfer Textarea data through CGI program

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

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.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>

test.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())/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>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>输入的文本内容为:$text_content</h2>";
print "</body>";
print "</html>";

1;

In the browser, the execution effect is as follows:


Transfer drop-down data through CGI program

HTML drop-down box code As follows:

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

test.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())/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>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>选择的网站是:$site</h2>";
print "</body>";
print "</html>";

1;

In the browser, the execution effect is as follows:


Using Cookies in CGI

A big shortcoming of the http protocol It just doesn’t judge the user’s identity, which brings great inconvenience to programmers. The emergence of the cookie function makes up for this shortcoming.

Cookie is to write record data on the customer's hard drive through the customer's browser while the customer accesses the script. , the data information will be retrieved the next time the customer accesses the script, so as to achieve the function of identity discrimination. Cookies are often used in identity verification.

 

Cookie syntax

http cookie is sent through the http header, which is earlier than the file transfer. The syntax of the set-cookie header is as follows:

Set-cookie:name=name;expires=date;path=path;domain=domain;secure
  • name=name: You need to set the cookie value (name cannot use ";" and ","), how many Use ";" to separate name values, for example: name1=name1;name2=name2;name3=name3.

  • expires=date: Cookie validity period, format: expires="Wdy,DD-Mon-YYYY HH:MM:SS"


  • path=path: Set the path supported by cookies. If path is a path, the cookie will be in this directory. Valid for all files and subdirectories, for example: path="/cgi-bin/". If path is a file, the cookie will be valid for this file, for example: path="/cgi-bin/cookie.cgi".

  • domain=domain: Domain name that is valid for cookies, for example: domain="www.php.cn"

  • secure: If this flag is given, it means that the cookie can only be passed through the https server of the SSL protocol.

  • The reception of cookies is achieved by setting the environment variable HTTP_COOKIE. CGI programs can obtain cookie information by retrieving this variable.


Cookie Settings

Cookie setting is very simple, the cookie will be sent separately in the http header. The following example sets UserID, Password and expires 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.php.cn;\n";
print "Set-Cookie:Path=/perl;\n";
print "Content-type:text/html\r\n\r\n";
...........其他 HTML 内容

Find Cookie

The cookie information retrieval page is very simple. Cookie information is stored in the CGI environment variable HTTP_COOKIE, and the storage format is as follows:

#!/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 result of the above example is:

User ID = XYZ
Password = XYZ123

CGI module

Perl provides many built-in CGI modules, the following two are commonly used:

  • CGI module

  • Berkeley cgi-lib.pl

The value of this environment variable indicates the MIME type of the information passed. Currently, the environment variable CONTENT_TYPE is generally: application/x-www-form-urlencoded, which indicates that the data comes from HTML forms.
If the information transmission method between the server and the CGI program is POST, this environment variable is 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 entered data.
COOKIE content in the client.
Provides client browser information including version number or other proprietary data.
The value of this environment variable indicates other path information immediately after the CGI program name. It often appears as a parameter to CGI programs.
If the information transfer method between the server and the CGI program is GET, the value of this environment variable is the information transferred. This information follows the CGI program name, separated by a question mark '?'.
The value of this environment variable is the IP address of the client sending the request, such as 192.168.1.67 above. This value is always present. And it is the unique identifier that the Web client needs to provide to the Web server, which can be used in CGI programs to distinguish different Web clients.
The value of this environment variable contains the host name of the client that sent the CGI request. If the query you want to query is not supported, there is no need to define this environment variable.
Provides the method by which the script is called. For scripts using the HTTP/1.0 protocol, only GET and POST are meaningful.
Full path of the CGI script
Name of the CGI script
This is the host name, alias or IP address of your WEB server.
The value of this environment variable contains the name and version number of the HTTP server that calls the CGI program. For example, the value above is Apache/2.2.14(Unix)