May 11, 2021 C++
7. Hello World! This is my first CGI program
12.. Use the GET method to pass information
13.. Simple URL instance: Get method
14.. Simple form example: GET method
15.. Use the POST method to pass information
16.. Pass check box data to the CGI program
17.. Pass the turntr button data to the CGI program
18.. Pass text area data to the CGI program
To better understand the concept of CGI, let's click on a hyperlink and browse a particular page or URL to see what happens.
However, the HTTP server is built in this way, and whenever a file in the directory is requested, the HTTP server sends back not the file, but as a program and sends the output generated by the execution back to the browser for display.
A public gateway interface (CGI) is a standard protocol that enables applications, called CGI programs or CGI scripts, to interact with Web servers and clients. These CGI programs can be written with Python, PERL, Shell, C, C, C, and so on.
The following illustration illustrates the architecture of CGI:
Before you program CGI, make sure that your web server supports CGI and is configured to handle CGI programs. A ll CGI programs performed by http servers must be in a preconfigured directory. T he directory is called the CGI directory and is customaryly named /var/www/cgi-bin. Although the CGI file is an executable file for C++, its extension by convention is .cgi.
By default, the Apache Web server is configured to run CGI programs in /var/www/cgi-bin. If you want to specify a different directory to run CGI scripts, you can modify the following sections in the httpd.conf file:
<Directory "/var/www/cgi-bin"> AllowOverride None Options ExecCGI Order allow,deny Allow from all </Directory> <Directory "/var/www/cgi-bin"> Options All </Directory>
Here, let's assume that the Web server is configured and running successfully, and that you can run any CGI program, such as Perl or Shell.
Take a look at the following C++ program:
#include <iostream> using namespace std; int main () { cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>Hello World - 第一个 CGI 程序</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "<h2>Hello World! 这是我的第一个 CGI 程序</h2>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Compile the code above, name the executable cplusplus .cgi, and save the file in the /var/www/cgi-bin directory. B efore you run the CGI program, use the chmod 755 cplusplus.cgi UNIX command to modify the file mode to ensure that the file is executable. Access the executable and you'll see the following output:
The above program is a simple program that writes its output on the STDOUT file, which is displayed on the screen. H ere, it's worth noting that the first line outputs Content-type:text/html\n\n?. T his line is sent back to the browser and specifies the type of content to display on the browser window. Y ou must understand the basic concepts of CGI in order to further write more complex CGI programs using Python. The C?CGI program can interact with any other external system, such as RDBMS.
Line Content-type:text/html\n is part of the HTTP header information, which is sent to the browser to better understand the content of the page. Http header information takes the form of:
HTTP 字段名称: 字段内容 例如 Content-type: text/html\r\n\r\n
There are some other important HTTP header information that is often used in your CGI programming.
Head information | describe |
---|---|
Content-type: | MIME string, define the returned file format.For example, Content-Type: Text / HTML. |
Expires: Date | The information becomes an invalid date.The browser uses it to determine when a page needs to be refreshed.The format of an effective date string should be 01 Jan 1998 12:00:00 GMT. |
Location: URL | This URL refers to the URL that should be returned instead of the requested URL.You can use it to redirect a request to any file. |
Last-modified: Date | The final modification date of the resource. |
Content-length: N | The length of the data to be returned, in bytes.The browser uses this value to represent the expected download time of a file. |
Set-Cookie: String | pass through string Set the cookie. |
All CGI programs have access to the following environment variables. These variables play a very important role in writing CGI programs.
variable name | describe |
---|---|
CONTENT_TYPE | The data type of the content.Use when the client sends additional content to the server.For example, file upload function. |
CONTENT_LENGTH | The information length of the query.Only available for POST requests. |
HTTP_COOKIE | Returns the set cookies in the form of a key & value. |
HTTP_USER_AGENT | The user agent requests the header field, submits the information of the user initiated the request, contains additional information of the browser name, version, and other platform sex. |
PATH_INFO | The path of the CGI script. |
QUERY_STRING | The URL encoded information is sent when the request is sent through the GET method, contains the parameters behind the URL symbol. |
REMOTE_ADDR | Send the IP address of the requested remote host.This is very useful when logging and authentication. |
REMOTE_HOST | A fully qualified name for issuing the requested host.If this information is not available, remove_addr can be used to get the IP address. |
REQUEST_METHOD | Method for issuing a request.The most common method is GET and POST. |
SCRIPT_FILENAME | The full path to the CGI script. |
SCRIPT_NAME | The name of the CGI script. |
SERVER_NAME | The host name or IP address of the server. |
SERVER_SOFTWARE | The name and version of the software running on the server. |
The following CGI program lists all CGI variables.
#include <iostream>
#include <stdlib.h>
using namespace std;
const string ENV[ 24 ] = {
"COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
"HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",
"HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",
"HTTP_HOST", "HTTP_USER_AGENT", "PATH",
"QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
"REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
"SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",
"SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",
"SERVER_SIGNATURE","SERVER_SOFTWARE" };
int main ()
{
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>CGI 环境变量</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table border = \"0\" cellspacing = \"2\">";
for ( int i = 0; i < 24; i++ )
{
cout << "<tr><td>" << ENV[ i ] << "</td><td>";
// 尝试检索环境变量的值
char *value = getenv( ENV[ i ].c_str() );
if ( value != 0 ){
cout << value;
}else{
cout << "环境变量不存在。";
}
cout << "</td></tr>\n";
}
cout << "</table><\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
In a real instance, you need to do a lot through the CGI program. Here's a CGI library written specifically for the C++ program, which we can download from ftp://ftp.gnu.org/gnu/cgicc/ and follow these steps to install the library:
$tar xzf cgicc-X.X.X.tar.gz $cd cgicc-X.X.X/ $./configure --prefix=/usr $make $make install
You can view the relevant library documentation by clicking on the CGI Lib Documentation.
You may have experienced situations where you need to pass some information from your browser to the Web server and finally to a CGI program. Typically, browsers use two methods to pass this information to the Web server, the GET and POST methods.
The GET method sends encoded user information appended to the page request. P ages and encoded information pass through ? Characters are separated as follows:
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
The GET method is the default way to pass information from the browser to the web server, and it generates a long string in the browser's address bar. D o not use the GET method when you pass passwords or other sensitive information to the server. T he GET method has a size limit and can pass up to 1024 characters in a request string.
When using the GET method, the QUERY_STRING http header is used to pass information, which can be accessed in CGI programs using QUERY_STRING environment variables.
You can pass information by following the key-value pair of a simple connection after the URL, or by using the GET method of the HTML-lt;FORM-gt; tag.
Here's a simple URL that uses the GET method to pass two values to hello_get.py program.
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
The following example cpp_get.cgi CGI program that handles input from a web browser. The information that is passed can be easily accessed by using the C?CGI library:
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>使用 GET 和 POST 方法</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("first_name");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "名:" << **fi << endl;
}else{
cout << "No text entered for first name" << endl;
}
cout << "<br/>\n";
fi = formData.getElement("last_name");
if( !fi->isEmpty() &&fi != (*formData).end()) {
cout << "姓:" << **fi << endl;
}else{
cout << "No text entered for last name" << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
Now, compile the program above, as follows:
$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc
Build cpp_get.cgi, put it in the CGI directory, and try to access it using the link below:
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
This results in the following:
名:ZARA 姓:ALI
Here's a simple example of using an HTML form and a submit button to pass two values. We'll use the same CGI script cpp_get.cgi process the input.
<form action="/cgi-bin/cpp_get.cgi" method="get">
名:<input type="text" name="first_name"> <br />
姓:<input type="text" name="last_name" />
<input type="submit" value="提交" />
</form>
Here's the actual output of the form above, enter your first and last name, and then click the Submit button to see the results.
A more reliable way to pass information to CGI programs is the POST method. T his approach packages information in the same way as the GET method, unlike putting information in a URL as a text string? I t is then passed, but as a separate message. The message is passed to the CGI script as standard input.
We also use the cpp_get.cgi program to handle the POST method. Let's use the same example to pass two values by using HTML forms and submit buttons, except this time we're not using the GET method, but the POST method, as follows:
<form action="/cgi-bin/cpp_get.cgi" method="post"> 名:<input type="text" name="first_name"><br /> 姓:<input type="text" name="last_name" /> <input type="submit" value="提交" /> </form>
We use check boxes when multiple options need to be selected.
The following instance of HTML code is a form with two check boxes:
<form action="/cgi-bin/cpp_checkbox.cgi" method="POST" target="_blank"> <input type="checkbox" name="maths" value="on" /> 数学 <input type="checkbox" name="physics" value="on" /> 物理 <input type="submit" value="选择学科" /> </form>
The following C++ program generates cpp_checkbox.cgi script that handles the input given by the Web browser through the check box.
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc formData;
bool maths_flag, physics_flag;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>向 CGI 程序传递复选框数据</title>\n";
cout << "</head>\n";
cout << "<body>\n";
maths_flag = formData.queryCheckbox("maths");
if( maths_flag ) {
cout << "Maths Flag: ON " << endl;
}else{
cout << "Maths Flag: OFF " << endl;
}
cout << "<br/>\n";
physics_flag = formData.queryCheckbox("physics");
if( physics_flag ) {
cout << "Physics Flag: ON " << endl;
}else{
cout << "Physics Flag: OFF " << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
We use a turn button when only one option needs to be selected.
The following instance of HTML code is a form with two turntable buttons:
<form action="/cgi-bin/cpp_radiobutton.cgi" method="post" target="_blank"> <input type="radio" name="subject" value="maths" checked="checked"/> 数学 <input type="radio" name="subject" value="physics" /> 物理 <input type="submit" value="选择学科" /> </form>
The following C++ program generates cpp_radiobutton.cgi script that handles input given by a Web browser through a single button.
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>向 CGI 程序传递单选按钮数据</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("subject");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "Radio box selected: " << **fi << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
We use the TEXTAREA element when we need to pass multiple lines of text to a CGI program.
The following example of HTML code is a form with a TEXTAREA box:
<form action="/cgi-bin/cpp_textarea.cgi" method="post" target="_blank"> <textarea name="textcontent" cols="40" rows="4"> 请在这里输入文本... </textarea> <input type="submit" value="提交" /> </form>
The following C++ program generates a cpp_textarea.cgi that handles input given by a Web browser through a text area.
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>向 CGI 程序传递文本区域数据</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("textcontent");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "Text Content: " << **fi << endl;
}else{
cout << "No text entered" << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
We use a pull-down box when more than one option is available, but only one or two options can be selected.
The following example of HTML code is a form with a pull-down box:
<form action="/cgi-bin/cpp_dropdown.cgi" method="post" target="_blank"> <select name="dropdown"> <option value="Maths" selected>数学</option> <option value="Physics">物理</option> </select> <input type="submit" value="提交"/> </form>
The following C++ program generates cpp_dropdown.cgi script that handles the input given by the web browser through the pull-down box.
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>向 CGI 程序传递下拉框数据</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("dropdown");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "Value Selected: " << **fi << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
The HTTP protocol is a stateless protocol. B ut for a business website, it needs to keep session information between pages. F or example, a user ends registration after completing steps on multiple pages. However, how to keep the user's session information in all web pages.
In many cases, the use of cookies is the most effective way to remember and track user preferences, purchases, commissions, and other information needed for a better visitor experience or website statistics.
The server sends some data to the visitor's browser in the form of a cookie. I f the browser accepts the cookie, the cookie is stored on the visitor's hard drive as a plain text record. C ookies are now retrieved when a visitor visits another page on the website. Once the cookie is found, the server knows what is stored.
A cookie is a plain text data record with 5 fields of variable length:
Sending cookies to your browser is very simple. T hese cookies are sent with the HTTP header before the Content-type field. Assuming you want to set UserID and Password as cookies, the steps for setting cookies are as follows:
#include <iostream>
using namespace std;
int main ()
{
cout << "Set-Cookie:UserID=XYZ;\r\n";
cout << "Set-Cookie:Password=XYZ123;\r\n";
cout << "Set-Cookie:Domain=www.w3cschool.cn;\r\n";
cout << "Set-Cookie:Path=/perl;\n";
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>CGI 中的 Cookies</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "设置 cookies" << endl;
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
From this example, we learned how to set cookies. We use the Set-Cookie HTTP header to set cookies.
Here, there are some properties that set cookies that are optional, such as Expires, Domain, and Path. It is worth noting that cookies were set before the line "Content-type:text/html\n\n?n" was sent.
Compile the above program, generate a setcookies .cgi, and try setting cookies using the link below. It sets four cookies on your computer:
/cgi-bin/setcookies.cgi
Retrieving all settings of cookies is very simple. Cookies are stored in the CGI environment HTTP_COOKIE in the following form:
key1=value1;key2=value2;key3=value3....
The following example shows how to get cookies.
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc cgi;
const_cookie_iterator cci;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>CGI 中的 Cookies</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table border = \"0\" cellspacing = \"2\">";
// 获取环境变量
const CgiEnvironment& env = cgi.getEnvironment();
for( cci = env.getCookieList().begin();
cci != env.getCookieList().end();
++cci )
{
cout << "<tr><td>" << cci->getName() << "</td><td>";
cout << cci->getValue();
cout << "</td></tr>\n";
}
cout << "</table><\n";
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
Now compile the above program, generate a getcookies .cgi, and try using the link below to get all the available cookies on your computer:
/cgi-bin/getcookies.cgi
This results in a list of the four cookies set in the last section and all other cookies on your computer:
UserID XYZ Password XYZ123 Domain www.w3cschool.cn Path /perl
In order to upload a file, the HTML form must set the enctype property to multipart/form-data. The input label with file type creates a "Browse" button.
<html> <body> <form enctype="multipart/form-data" action="/cgi-bin/cpp_uploadfile.cgi" method="post"> <p>文件:<input type="file" name="userfile" /></p> <p><input type="submit" value="上传" /></p> </form> </body> </html>
You can try the code above on your own server.
Here are the scripts used to handle file uploads cpp_uploadfile.cpp:
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main ()
{
Cgicc cgi;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>CGI 中的文件上传</title>\n";
cout << "</head>\n";
cout << "<body>\n";
// 获取要被上传的文件列表
const_file_iterator file = cgi.getFile("userfile");
if(file != cgi.getFiles().end()) {
// 在 cout 中发送数据类型
cout << HTTPContentHeader(file->getDataType());
// 在 cout 中写入内容
file->writeToStream(cout);
}
cout << "<文件上传成功>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
The above example is written in a cout stream, but you can open the file stream and save the uploaded file content in a file at the destination location.