C++ Introductory Tutorial||C++ Web Programming

C++ web programming

What are CGIs?

  • Common Gateway Interface (CGI), is a set of standards that defines how information is exchanged between web servers and client-side scripts.
  • The CGI specification is currently maintained by the NCSA, which defines CGI as follows:
  • Common Gateway Interface (CGI) is an interface standard for connecting external gateway programs to information servers (such as HTTP servers).
  • The current version is CGI/1.1, and a CGI/1.2 version is in progress.

web browsing

To better understand the concept of CGI, let's click on a hyperlink, browse to a specific web page or URL, and see what happens.

  • Your browser contacts the HTTP web server and requests the URL, which is the file name.
  • The web server will parse the URL and look for the filename. If the requested file is found, the web server sends the file back to the browser, otherwise it sends an error message indicating that you requested a wrong file.
  • A web browser gets a response from a web server and, depending on the response received, displays a file or an error message.

However, the HTTP server built in this way, whenever a file in the directory is requested, the HTTP server does not send back the file, but executes it in the form of a program, and sends the output generated by the execution back to the browser for display come out.

Common Gateway Interface (CGI), is a standard protocol that enables application programs (called CGI programs or CGI scripts) to interact with Web servers and clients. These CGI programs can be written in Python, PERL, Shell, C or C++, etc.

CGI architecture diagram

The following diagram demonstrates the architecture of CGI:

Web server configuration

Before you start CGI programming, make sure your Web server supports CGI and is configured to handle CGI programs. All CGI programs executed by the HTTP server must be in the preconfigured directory. This directory is called the CGI directory and is named by convention /var/www/cgi-bin. Although a CGI file is a C++ executable, by convention it has the extension  .cgi .

By default, the Apache web server is configured to run CGI programs in /var/www/cgi-bin. If you want to specify another directory to run CGI scripts, you can modify the following section 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, we assume that the Web server has been configured and can run successfully, you can run any CGI program, such as Perl or Shell, etc.

The first CGI program

Consider 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 - The first CGI program</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<h2>Hello World! This is my first CGI program</h2>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Compile the above code, name the executable file cplusplus.cgi, and save this file in the /var/www/cgi-bin directory. Before running the CGI program, please 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:

Hello World! This is my first CGI program

The above C++ program is a simple program that writes its output to the STDOUT file, ie displays it on the screen. Here, it is worth noting that the first line outputs  Content-type: text/html\r\n\r\n . This line is sent back to the browser and specifies the type of content to be displayed on the browser window. You must understand the basic concepts of CGI, so that you can further use Python to write more complex CGI programs. C++ CGI programs can interact with any other external system such as an RDBMS.

HTTP header information

The line  Content-type: text/html\r\n\r\n  is part of the HTTP header information that is sent to the browser to better understand the content of the page. The form of HTTP header information is as follows:

HTTP field name: field content
 
For example
Content-type: text/html\r\n\r\n

There are some other important HTTP headers that will be used frequently in your CGI programming.

header information describe
Content-type: A MIME string defining the returned file format. For example Content-type: text/html.
Expires: Date The date the information became invalid. Browsers use it to determine when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT.
Location: URL This URL refers to the URL that should be returned, not the requested URL. You can use this to redirect a request to an arbitrary file.
Last-modified: Date The date the resource was last modified.
Content-length: N The length of the data to return, in bytes. Browsers use this value to indicate the estimated download time for a file.
Set-Cookie: String  Set cookie by  string .

CGI environment variables

All CGI programs can access 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. Used when the client sends additional content to the server. For example, functions such as file upload.
CONTENT_LENGTH The message length of the query. Only available for POST requests.
HTTP_COOKIE Returns the set cookies as key & value pairs.
HTTP_USER_AGENT The user agent request header field is used to submit information about the request initiated by the user, including the name, version and other platform-specific additional information of the browser.
PATH_INFO The path to the CGI script.
QUERY_STRING URL-encoded information when a request is sent via the GET method, including parameters after the question mark in the URL.
REMOTE_ADDR The IP address of the remote host making the request. This is very useful for logging and authentication.
REMOTE_HOST The fully qualified name of the host making the request. If this information is not available, REMOTE_ADDR can be used to obtain the IP address.
REQUEST_METHOD The method used to make the request. The most common methods are GET and POST.
SCRIPT_FILENAME Full path to the CGI script.
SCRIPT_NAME The name of the CGI script.
SERVER_NAME The hostname 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;
}

C++ CGI library

In a real instance, you would need to perform many operations through a CGI program. Here is a CGI library specially written for C++ programs, we can download this CGI library from  ftp://ftp.gnu.org/gnu/cgicc/  , and follow the steps below 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 click  C++ CGI Lib Documentation to view related library documents.

GET and POST methods

You've probably come across a situation when you needed to pass some information from your browser to a web server and finally to a CGI program. Usually the browser will use two methods to transmit this information to the Web server, namely the GET and POST methods.

Pass information using the GET method

The GET method sends encoded user information appended to the page request. Pages and encoded information are separated by a ? character, as follows:

http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2

The GET method is the default method of transferring information from the browser to the web server, and it will generate a long string of characters in the browser's address bar. Do not use the GET method when you are passing passwords or some other sensitive information to the server. The GET method has a size limit, and a maximum of 1024 characters can be passed in a request string. 

When using the GET method, the information is passed using the QUERY_STRING http header, which can be accessed using the QUERY_STRING environment variable in the CGI program.

You can pass information by simply concatenating key-value pairs following the URL, or by using the GET method of the HTML <FORM> tag.

Simple URL Example: Get Method

Below is a simple URL that uses the GET method to pass two values ​​to the hello_get.py program.

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

The following example generates  the cpp_get.cgi  CGI program for processing input given by a Web browser. The passed information 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 above program as follows:

$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

Generate 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 produces the following result:

Name: ZARA
Surname: ALI

Simple form example: GET method

Below is a simple example using an HTML form and a submit button to pass two values. We will use the same CGI script cpp_get.cgi to 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>

Below is the actual output of the above form, please enter first and last name and click submit button to see the result.

Pass information using the POST method

A more reliable method of passing information to a CGI program is the POST method. This method packs information in the same way as the GET method, except that instead of passing the information as a text string after the ? in the URL, it passes it in a separate message. This message is passed to the CGI script on standard input.

We also use the cpp_get.cgi program to handle the POST method. Let us take the same example and pass two values ​​by using HTML form and submit button, only this time instead of GET method we use 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>

Pass checkbox data to CGI program

We use checkboxes when multiple options need to be selected.

The following HTML code example 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="Select subject" />
</form>

The following C++ program generates the cpp_checkbox.cgi script for processing input given by a web browser via check boxes.

#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;
}

Pass radio button data to CGI program

We use radio buttons when only one option needs to be selected.

The following HTML code example is a form with two radio buttons:

<form action="/cgi-bin/cpp_radiobutton.cgi" 
         method="post" 
         target="_blank">
<input type="radio" name="subject" value="maths" 
                                    checked="checked"/> math
<input type="radio" name="subject" value="physics" /> 物理
<input type="submit" value="Select subject" />
</form>

The following C++ program generates the cpp_radiobutton.cgi script that handles the input given by the web browser via the radio buttons.

#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;
}

Pass textarea data to a CGI program

We use the TEXTAREA element when multiple lines of text need to be passed to a CGI program.

The following HTML code example 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">
Please enter text here...
</textarea>
<input type="submit" value="提交" />
</form>

The following C++ program generates the cpp_textarea.cgi script for handling input given by the web browser through the 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;
}

Pass the drop-down box data to the CGI program

We use dropdown boxes when there are multiple options available, but only one or two options can be selected.

The following HTML code example is a form with a drop-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 the cpp_dropdown.cgi script for processing input given by a web browser through a drop-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;
}

Using Cookies in CGI

The HTTP protocol is a stateless protocol. But for a commercial website, it needs to keep session information between different pages. For example, a user ends registration after completing several pages of steps. But how to keep user's session information across all web pages.

In many cases, the use of cookies is the most effective method of remembering and tracking user preferences, purchases, commissions, and other information needed for a better visitor experience or website statistics.

how it works

The server sends some data to the visitor's browser in the form of a cookie. If the browser accepts the cookie, the cookie is stored as a plain text record on the visitor's hard drive. Now, when a visitor visits another page on the website, the cookie is retrieved. Once the cookie is found, the server knows what was stored.

A cookie is a plain text data record with 5 variable-length fields:

  • Expires :  The expiration date of the cookie. If this field is left blank, the cookie will expire when the visitor exits the browser.
  • Domain :  The domain name of the website.
  • Path :  The path of the directory or web page where the cookie is set. This field can be left blank if you want to retrieve cookies from any directory or web page.
  • Secure :  If this field contains the word "secure", then the cookie can only be retrieved through a secure server. If this field is left blank, the restriction does not exist.
  • Name=Value :  The cookie is set and retrieved as a key-value pair.

set cookies

Sending cookies to the browser is very simple. These cookies are sent with the HTTP header before the Content-type field. Suppose you want to set UserID and Password as cookies, the steps to set 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, some attributes for setting cookies are optional, such as Expires, Domain, and Path.  It's worth noting that the cookies are set before the line "Content-type:text/html\r\n\r\n is sent  .

Compile the above program, generate setcookies.cgi, and try to set cookies using the link below. It sets four cookies on your computer:

/cgi-bin/setcookies.cgi

Get Cookies

Retrieving all set cookies is very simple. Cookies are stored in the CGI environment variable HTTP_COOKIE, and they have the following form:

key1=value1;key2=value2;key3=value3....

The following example demonstrates 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 getcookies.cgi, and try to get all available cookies on your computer using the link below:

/cgi-bin/getcookies.cgi

This produces a list showing the four cookies set in the previous section along with all other cookies on your computer:

UserID XYZ 
Password XYZ123 
Domain www.w3cschool.cn 
Path /perl 

File upload example

In order to upload a file, the HTML form must have the enctype attribute set to  multipart/form-data . An input tag with a 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 is the script cpp_uploadfile.cpp for handling file uploads  :

#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 writes content in  the cout  stream, but you can open the file stream and save the uploaded file content in a file at the target location.

 

Guess you like

Origin blog.csdn.net/m0_69824302/article/details/131054272