开源项目之---cgi ( cgicc )

CGI是: “公共网关接口”(Common Gateway Interface)的简称,是HTTP服务器与其它程序进行“交谈”的一种工具,其程序须运行在网络服务器上。CGI是一段程序,它运行在Server上,提供同客户端 Html页面的接口。


CGI的功能:通常情况下CGI程序被用来解释处理来自表单的输入信息,在服务器产生相应的处理,并将相应的信息反馈给浏览器。CGI程序使网页具有交互功能。 


CGI处理步骤: 通过Internet把用户请求送到服务器服务器接收用户请求并交给CGI程序处理CGI程序把处理结果传送给服务器服务器把结果送回到用户

CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。


CGI程序的输出: CGI程序中的标准输出是经过重定向了的。CGI程序并不会在服务器上产生任何的输出内容,而是被重定向到客户浏览器。这样,如果编写一个C的CGI程序的时候,把一个HTML文档输出到它的stdout上,这个HTML文档会被在客户端的浏览器中显示出来。这也是CGI程序的一个基本原理。



CGI程序第一行输出的内容必须是: "Content-Type:text/html"这个输出作为HTML的文件头。因为CGI不仅可以像浏览器输出HTML文本,而且可以输出图像,声音之类的东西,http服务器向远程发送文件时要说明文件类型。


两个重要的CGI环境变量QUERY-STRING:GET方法表单输入的数据,URL中间号后的内容。

CONTENT-LENGTH:POST方法输入的数据的字节数。

CGI环境变量列表:    
SERVER-NAME:运行CGI序为机器名或IP地址。  
SERVER-INTERFACE:WWW服务器的类型,如:CERN型或NCSA型。  
SERVER-PROTOCOL:通信协议,应当是HTTP/1.0。  
SERVER-PORT:TCP端口,一般说来web端口是80。  
HTTP-ACCEPT:HTTP定义的浏览器能够接受的数据类型。  
HTTP-REFERER: 发送表单的文件URL。(并非所有的浏览器都传送这一变量)  
HTTP-USER-AGENT:发送表单的浏览器的有关信息。  
GETWAY-INTERFACE:CGI程序的版本,在UNIX下为 CGI/1.1。 
PATH-TRANSLATED: PATH-INFO中包含的实际路径名。  
PATH-INFO:浏览器用GET方式发送数据时的附加路径。  
SCRIPT-NAME: CGI程序的路径名。  
QUERY-STRING:表单输入的数据,URL中间号后的内容。  
REMOTE-HOST:发送程序的主机名,不能确定该值。  
REMOTE-ADDR:发送程序的机器的IP地址。  
REMOTE-USER:发送程序的人名。  
CONTENT-TYPE:POST发送,一般为applioation/xwww-form-urlencoded。 

CONTENT-LENGTH:POST方法输入的数据的字节数。 


CGICC----用C++实现的一个cgi库 

cgicc是开发cgi程序的c++库,它是基于stl的,从使用上来说,可以把它分成两个部分:第一部分是输入输出的处理和封装,它包括 Cgicc、CgiEnvironment、CgiInput、FormEntry和FormFile类,第二部分是数据输出模块,它们是以MStreamable为基类的封装了HTTPHeader和HTML元素的一系列子类。HTTPCookie是继承MStreamable的,但是,对于输入Cookie来说,也是通过HTTPCookie来表示的,也许这是因为Cookie通常需要在不同请求中保留而设计的。

 
  Cgicc:封装了Web Server和CGI程序之间的数据过渡功能,对于Web Server来说它是参数的输出对象,对于CGI程序来说它是提取Web Server传递过来的数据(包括浏览器信息、Web Server自身的数据和用户提交的数据)的代理。
  
  CgiEnvironment:表示CGI运行的环境变量,这些环境变量是Web Server初始化的,也就CGI需要处理的数据,它是作为Cgicc对象的数据成员而保存的,当然开发者也可以通过getEnvironment()来直接获得CgiEnvironment的const引用。
  
  CgiInput:这是对于Web Server数据输入方式的抽象,对于传统CGI程序来说它就是标准输入,对于FastCGI来说,它是一个独立的sockket,而且对于FastCGI或者是用户自定义的参数输入方式来说,可以通过继承CgiInput来生成定制的类,只要在子类中覆盖read、getenv成员函数就能够很好地工作。
            
  FormEntry和FormFile是对于用户提交的数据的抽象,FormEntry是描述普通name-value对的抽象,而FormFile则是对用户上传的文件的抽象。事实上FormEntry和FormFile的本质差别就是FomFile多了一个文件名和文件类型。 
  
  输出数据的封装类比较多,这里只是说说它设计的基本思想,如果需要详细的接口说明,可以参看cgicc的帮助文档。
  cgicc中重载了流输出函数:CGICC_API std::ostream& operator<<(std::ostream& out, const MStreamable& obj);在具有输出功能的基类MStreamable里声明为友元函数,这样只要以  "outstream << MStreamable" 的形式调用的话,就会调用这个自定义的输出流函数,在这个自定义的流输出函数中,会调用MStreamable.render(outstream), 也就是说只要在MStreamable的子类中覆盖render成员函数就能够定制之类的输出。在应用中,通常之类会把自己的内部数据转换为字符串,然后调用outstream << data_str ,只要在outstream的成员函数中覆盖<<操作符,就能够实现各种输出协议(当然也包括FastCGI协议),在传统的CGI中,这个outstream就是std::cout对象。


  cgicc的详细说明文档及案例:cgicc-3.2\doc\html\index.html 

例子:

html网页:

<form method="post" action="http://change_this_path/cgi-bin/foo.cgi">
Your name : <input type="text" name="name" /><br />
Your age : <input type="text" name="age" /><br />
Your sex : <input type="radio" name="sex" value="male"checked="checked" />Male
<input type="radio" name="sex" value="female" />Female <br />
</form>
cgi应用程序:

#include <iostream>
#include <vector>
#include <string>

#include "cgicc/Cgicc.h"
#include "cgicc/HTMLClasses.h"

using namespace std;
using namespace cgicc;

int 
main(int argc, 
     char **argv)
{
   try {
      Cgicc cgi;

      // Send HTTP header
      cout << HTTPHTMLHeader() << endl;

      // Set up the HTML document
      cout << html() << << head(title("Cgicc example")) << endl;
      cout << body() << endl;

      // Print out the submitted element
      form_iterator name = cgi.getElement("name");
      if(name != cgi.getElements().end()) {
         cout << "Your name: " << **name << endl;
      }

      // Close the HTML document
      cout << body() << html();
   }
   catch(exception& e) {
      // handle any errors - omitted for brevity
   }
}

Initialization

The three main classes of cgicc you will use to process the submitted data are cgicc::Cgicc, cgicc::CgiEnvironment, and cgicc::FormEntry. These classes will be explained in detail later; for now, it is sufficient to know that:

  • The class cgicc::Cgicc is used for retrieving information on the submitted form elements.

  • The class cgicc::CgiEnvironment is used to retrieve information on environment variables passed from the HTTP server.

  • The class cgicc::FormEntry is used to extract various types of data from the submitted form elements.
All of cgicc's functionality is accessed through class cgicc::Cgicc. Thus, the first step in CGI processing is to instantiate an object of type cgicc::Cgicc:

or

using namespace cgicc;
Cgicc cgi;

Upon instantiation, the class cgicc::Cgicc parses all data passed to the CGI script by the HTTP server.

Since errors are handled using exceptions, you may wish to wrap your CGI code in a try block to better handle unexpected conditions:

try {
   cgicc::Cgicc cgi;
}

catch(exception& e) {
   // Caught a standard library exception
}


Extracting Form Information

Each element of data entered by the user is parsed into a cgicc::FormEntry. A cgicc::FormEntry contains methods for accessing data as strings, integers, and doubles. In the form mentioned above, a user would enter their name, age, and sex. Regardless of the type of value, the data is accessed using cgicc::FormEntry (Note: this is not entirely true. For uploaded files, the data is accessed via the class cgicc::FormFile). You obtain cgicc::FormEntry objects via cgicc::Cgicc's getElement methods, all of which return typedefs of C++ standard template library (STL) iterators:

cgicc::form_iterator name = cgi.getElement("name");

If the item is not found, the iterator will refer to an invalid element, and should not be dereferenced using operator* or operator->. cgicc::Cgicc provides methods for determining whether an iterator refers to a valid element:

if(name != cgi.getElements().end()) {
   // iterator refers to a valid element
}


Output of Form Data

Once you have a valid element, you will more than likely want to do something with the data. The simplest thing to do is just echo it back to the user. You can extract a string from a cgicc::FormEntry by calling the getValue method. Since ostream has an overload for writing basic_string objects, it is trivial to output objects of this type:

cout << "Your name is " << name->getValue() << endl;

Since both iterator and cgicc::FormEntry overload operator*, the code given above may also be written as:

cout << "Your name is " << **name << endl;

The first * returns an object of type cgicc::FormEntry, and the second * returns an object of type string


The HTTP Response

A CGI response will generally consist of an HTML document. The HTTP protocol requires that a certain set of headers precede all documents, to inform the client of the size and type of data being received, among other things. In a normal CGI response, the HTTP server will take care of sending many of these headers for you. However, it is necessary for the CGI script to supply the type of content it is returning to the HTTP server and the client. This is done by emitting aContent-Type header. If you're interested, the full HTTP 1.1 specification may be found in RFC 2068 athttp://www.w3.org/Protocols/rfc2068/rfc2068

cgicc provides several classes for outputting HTTP headers, all of which begin withHTTP. A standard HTML 4.0 document need only output a single header:

cout << HTTPHTMLHeader() << endl;

This will generate the output

Content-Type: text/html\n\n

Output of Form Data

cgicc provides one class for every HTML tag defined in the HTML 4.0 standard in the header file "cgicc/HTMLClasses.h". These classes have the same name as the HTML tags. For example, in HTML, to indicate the start of a document you write<html> ; this can be accomplished using cgicc by writing

cout << html() << endl;

The class html keeps state internally, so the code above will produce as output<html>; conversely, the code

cout << html() << "html text!" << html() << endl;

will produce as output <html>html text!</html>.

All of cgicc's HTML output classes are subclasses of the abstract class cgicc::HTMLElement. You can embed the text for the element directly in the constructor:

cout << html("html text!") << endl;

Furthermore, it is possible to embed one cgicc::HTMLElement in another:

cout << head(title("Title")) << endl;

This produces as output

<head><title>Title</title></head>

And, if you wish be more specific about the type of HTML 4.0 you are going to return (strict, transitional, or frameset), you can use the classcgicc::HTMLDoctype before the cgicc::html tag:

cout << HTMLDoctype(HTMLDoctype::eStrict) << endl;

which produces

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">

More Complex HTML Output

In real HTML, most tags possess a set of attributes. For example, the HTML <img> tag requires certain attributes specifying the source image file, the image width, height, and so on. There are a bewildering number of possible attributes in HTML 4.0. For a definitive list, see the HTML 4.0 specification athttp://www.w3.org/TR/REC-html40/ A typical<img> tag might look like:

<img src="file.jpg" width="100" height="100" alt="description" />

This tag has four attributes: src, width, height, andalt, with the values file.jpg, 100, 100, and description, respectively. Attributes in HTML tags are represented by the classcgicc::HTMLAttribute, which essentially is a name/value pair. To build ancgicc::HTMLElement containingcgicc::HTMLAttribute objects, use theset method on cgicc::HTMLElement. To generate the<img> tag given above:

cout << img().set("src", "file.jpg")
             .set("width", "100").set("height", "100")
             .set("alt", "description") << endl;

In a similar way, multiple cgicc::HTMLElement objects may be embedded at the same level inside anothercgicc::HTMLElement. To build ancgicc::HTMLElement containing multiple embeddedcgicc::HTMLElement objects, use theadd method on cgicc::HTMLElement:

cout << tr().add(td("0")).add(td("1")).add(td("2")) << endl;

This produces as output

<tr><td>0</td><td>1</td><td>2</td></tr>


Notes on Output

All of cgicc's output is written to the C++ standard output stream, cout. It is not necessary to use cgicc's HTML output classes; they are provided as a convenience. If you prefer, you may output the HTML code directly tocout

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值