CGI输入输出原理
CGI的输入/输出方法:CGI程序通过标准输入(STDIN)和标准输出(STDOUT)来进行输入输出,STDIN和STDOUT是两个预先定义好的文件指针。你可以利用文件读写函数来对其进行操纵。
此外CGI程序还通过环境变量来得到输入,只不过环境变量中提供的是一些常用的信息,并且通常不包括用户在WEB页面中输入的信息(除使用下面讲的GET方法时,通过检查环境变量QUERY_STRING来得到输入数据),而STDIN通常用来传递用户输入的信息。在普通CGI程序开发中我们需要关心的环境变量有以下这些:
一部分是与WEB服务器有关的环境变量:
一部分是与运行CGI有关的:
一部分是与客户方有关的:
在输入时所使用的POST/GET方法:在WEB页面向CGI发送数据时通常采用两种方法:GET/POST,GET方法将数据附加在URL后发送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通过检查环境变量QUERY_STRING来得到输入数据。而POST方法则会将数据送入CGI程序的STDIN输入流。在表单(FORM)中的各个变量都会成为name=value的形式向WEB服务器发送,多个数据间用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定义的INPUT、SELECT或TEXTAREA等标置(Tag)名字,值是用户输入或选择的标置值。
有了上面的知识我们就可以马上写一个简单的CGI程序了。代码如下:
void main(void){// 本程序将用户输入的数据打印出来 fprintf(stdout,"content-type: text/plain/n/n"); // 输出一个CGI标题,这行代码的意义后面会讲解 char *pszMethod; pszMethod = getenv("REQUEST_METHOD"); if(strncmp(pszMethod,"GET") == 0) {// GET method //读取环境变量来获取数据 fprintf(stdout,"input data is :/n%s",getenv("QUERY_STRING")); } else {// POST method //读取STDIN来获取数据 int iLength=atoi(getenv("CONTENT_LENGTH")); fprintf(stdout,"input data is :/n"); for(int i=0;i<iLength;i++) { char cGet=fgetchar(stdin); fputchar(stdout,cGet); } }}>
如上面说讲,在CGI程序输出时必须先输出一个CGI标题,标题共有以下三类:
注意每种标题后都必须跟一个换行和一个空行。
MIME类型以类型/子类型的形式来表示,下面是一些常用的类型/子类型的组合:
有了上面的知识我们就可以写出一些CGI程序,首先需要对输入数据进行分析,方法为:每当找到字符=,标志着一个Form变量名字的结束;每当找到字符& ,标志着一个Form变量值的结束。请注意输入数据的最后一个变量的值不以&结束。这样我们可以将输入数据分解为一组一组的指。
但随后会发现CGI的输入并不规则,例如有时会出现类似下面格式的输入字符号串:filename=hello&cmd=world+I%27,这是因为浏览器对一些上传的特殊字符进行了编码,所以在将数据分解开后需要进行解码,解码规则为:+:将+转换成空格符;%xx:用其十六进制ASCII码值表示的特殊字符(%做为转意符)。根据值xx将其转换成相应的ASCII字符。对Form变量名和变量值都要进行这种转换。下面是一个对Form数据进行分析并将结果回送给Web服务器的CGI程序。
#include #include #include int htoi(char *); main() { int i,n; char c; printf (″Contenttype: text/plain/n/n″); n=0; if (getenv(″CONTENT-LENGTH″)) n=atoi(getenv(″CONTENT-LENGTH″)); for (i=0; i<n;i++){ int is-eq=0; c=getchar(); switch (c){ case ′&′: c=′/n′; break; case ′+′: c=′ ′; break; case ′%′:{ char s[3]; s[0]=getchar(); s[1]=getchar(); s[2]=0; c=htoi(s); i+=2; } break; case ′=′: c=′:′; is-eq=1; break; }; putchar(c); if (is-eq) putchar(′ ′); } putchar (′/n′); fflush(stdout); } /* convert hex string to int */ int htoi(char *s) { char *digits=″0123456789ABCDEF″; if (islower (s[0])) s[0]=toupper(s[0]); if (islower (s[1])) s[1]=toupper(s[1]); return 16 * (strchr(digits, s[0]) -strchr (digits,′0′)) +(strchr(digits,s[1])-strchr(digits,′0′)); }>
上面的程序首先输出一个MIME头信息给Web服务器,检查输入中的字符数,并循环检查每一个字符。
当发现字符为&时,意味着一个名字/值对的结束,程序输出一个空行;当发现字符为+时,将它转换成空
格; 当发现字符为%时,意味着一个两字符的十六进制值的开始,调用htoi()函数将随后的两个字符转换
为相应的ASCII字符;当发现字符为=时,意味着一个名字/值对的名字部分的结束,并将它转换成字符:。
最后将转换后的字符输出给Web服务器。
开发CGI程序可以按照下面的步骤进行:
1、判断数据输入方法为GET或是POST。
2、读取数据,根据分隔符号&分解每个接收的表单变量,并同时对数据进行解码。
3、处理数据。
4、输出CGI标题,输出HTML数据。
5、退出。利用C语言开发CGI需要自己对输入的数据进行分析,但字符号串处理并非C语言的强项,所以我向
大家推荐一套我认为比较不错的开发包,CGIC,(由http://www.boutell.com/boutell/免费提供)。
我对开发包中所提供的文件进行了少量的修改,并用VC6作者成为LIB。下载后可以看看该开发包所提供
的说明,该说明很详细不但给出例子代码而且对各个函数都有详细的解说。
一部分是与WEB服务器有关的环境变量:
一部分是与运行CGI有关的:
一部分是与客户方有关的:
在输入时所使用的POST/GET方法:在WEB页面向CGI发送数据时通常采用两种方法:GET/POST,GET方法将数据附加在URL后发送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通过检查环境变量QUERY_STRING来得到输入数据。而POST方法则会将数据送入CGI程序的STDIN输入流。在表单(FORM)中的各个变量都会成为name=value的形式向WEB服务器发送,多个数据间用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定义的INPUT、SELECT或TEXTAREA等标置(Tag)名字,值是用户输入或选择的标置值。
有了上面的知识我们就可以马上写一个简单的CGI程序了。代码如下:
void main(void){// 本程序将用户输入的数据打印出来 fprintf(stdout,"content-type: text/plain/n/n"); // 输出一个CGI标题,这行代码的意义后面会讲解 char *pszMethod; pszMethod = getenv("REQUEST_METHOD"); if(strncmp(pszMethod,"GET") == 0) {// GET method //读取环境变量来获取数据 fprintf(stdout,"input data is :/n%s",getenv("QUERY_STRING")); } else {// POST method //读取STDIN来获取数据 int iLength=atoi(getenv("CONTENT_LENGTH")); fprintf(stdout,"input data is :/n"); for(int i=0;i<iLength;i++) { char cGet=fgetchar(stdin); fputchar(stdout,cGet); } }}>
如上面说讲,在CGI程序输出时必须先输出一个CGI标题,标题共有以下三类:
注意每种标题后都必须跟一个换行和一个空行。
MIME类型以类型/子类型的形式来表示,下面是一些常用的类型/子类型的组合:
有了上面的知识我们就可以写出一些CGI程序,首先需要对输入数据进行分析,方法为:每当找到字符=,标志着一个Form变量名字的结束;每当找到字符& ,标志着一个Form变量值的结束。请注意输入数据的最后一个变量的值不以&结束。这样我们可以将输入数据分解为一组一组的指。
但随后会发现CGI的输入并不规则,例如有时会出现类似下面格式的输入字符号串:filename=hello&cmd=world+I%27,这是因为浏览器对一些上传的特殊字符进行了编码,所以在将数据分解开后需要进行解码,解码规则为:+:将+转换成空格符;%xx:用其十六进制ASCII码值表示的特殊字符(%做为转意符)。根据值xx将其转换成相应的ASCII字符。对Form变量名和变量值都要进行这种转换。下面是一个对Form数据进行分析并将结果回送给Web服务器的CGI程序。
#include #include #include int htoi(char *); main() { int i,n; char c; printf (″Contenttype: text/plain/n/n″); n=0; if (getenv(″CONTENT-LENGTH″)) n=atoi(getenv(″CONTENT-LENGTH″)); for (i=0; i<n;i++){ int is-eq=0; c=getchar(); switch (c){ case ′&′: c=′/n′; break; case ′+′: c=′ ′; break; case ′%′:{ char s[3]; s[0]=getchar(); s[1]=getchar(); s[2]=0; c=htoi(s); i+=2; } break; case ′=′: c=′:′; is-eq=1; break; }; putchar(c); if (is-eq) putchar(′ ′); } putchar (′/n′); fflush(stdout); } /* convert hex string to int */ int htoi(char *s) { char *digits=″0123456789ABCDEF″; if (islower (s[0])) s[0]=toupper(s[0]); if (islower (s[1])) s[1]=toupper(s[1]); return 16 * (strchr(digits, s[0]) -strchr (digits,′0′)) +(strchr(digits,s[1])-strchr(digits,′0′)); }>
上面的程序首先输出一个MIME头信息给Web服务器,检查输入中的字符数,并循环检查每一个字符。
当发现字符为&时,意味着一个名字/值对的结束,程序输出一个空行;当发现字符为+时,将它转换成空
格; 当发现字符为%时,意味着一个两字符的十六进制值的开始,调用htoi()函数将随后的两个字符转换
为相应的ASCII字符;当发现字符为=时,意味着一个名字/值对的名字部分的结束,并将它转换成字符:。
最后将转换后的字符输出给Web服务器。
开发CGI程序可以按照下面的步骤进行:
1、判断数据输入方法为GET或是POST。
2、读取数据,根据分隔符号&分解每个接收的表单变量,并同时对数据进行解码。
3、处理数据。
4、输出CGI标题,输出HTML数据。
5、退出。利用C语言开发CGI需要自己对输入的数据进行分析,但字符号串处理并非C语言的强项,所以我向
大家推荐一套我认为比较不错的开发包,CGIC,(由http://www.boutell.com/boutell/免费提供)。
我对开发包中所提供的文件进行了少量的修改,并用VC6作者成为LIB。下载后可以看看该开发包所提供
的说明,该说明很详细不但给出例子代码而且对各个函数都有详细的解说。