#include从本质上来看,程序先从CONTENT_LENGTH环境变量中得到数据的字长,然后读取相应长度的字符串。因为数据内容在传输的过程中是经过了编码的,所以必须进行相应的解码。编码的规则很简单,主要的有这几条:#include #define MAXLEN 80 #define EXTRA 5 /* 4个字节给字段"data", 1个字节留给"=" */ #define MAXINPUT MAXLEN+EXTRA+2 /* 1个字节留给换行符,还有一个留给后面的NULL */ #define DATAFILE "../data/data.txt" /* 要被添加数据的文件 */ void unencode(char *src, char *last, char *dest) { for(; src != last; src++, dest++) if(*src == '+') *dest = ' '; else if(*src == '%') { int code; if(sscanf(src+1, "%2x", &code) != 1) code = '?'; *dest = code; src +=2; } else *dest = *src; *dest = '\n'; *++dest = '\0'; } int main(void) { char *lenstr; char input[MAXINPUT], data[MAXINPUT]; long len; printf("%s%c%c\n", "Content-Type:text/html;charset=GB2312",13,10); printf(" Response \n"); lenstr = getenv("CONTENT_LENGTH"); if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN) printf("表单提交错误."); else { FILE *f; fgets(input, len+1, stdin); unencode(input+EXTRA, input+len, data); f = fopen(DATAFILE, "a"); if(f == NULL) printf("
对不起,意外错误,不能够保存你的数据."); else fputs(data, f); fclose(f); printf("
非常感谢,您的数据已经被保存!
%s",data); } return 0; }
1. 表单中每个每个字段用字段名后跟等号,再接上上这个字段的值来表示,每个字段之间的内容用&连结;
2. 所有的空格符号用加号代替,所以在编码码段中出现空格是非法的;
3. 特殊的字符比如标点符号,和一些有特定意义的字符如“+”,用百分号后跟其对应的ACSII码值来表示。
例如:如果用户输入的是:
Hello there!
那么数据传送到服务器的时候经过编码,就变成了data=Hello+there%21 上面的unencode()函数就是用来把编码后的数据进行解码的。在解码完成后,数据被添加到data.txt文件的尾部,并在浏览其中回显出来。
把文件编译完成后,把它改名为mult.cgi后放在CGI目录中就可以被表单调用了。
gcc -o mult.cgi mult.c
下面给出了其相应的html表单:
注意: ../data/data.txt的文件应该提前建立,而且文件属性应该为666.
chmod 666 ../data/data.txt
事实上,这个程序只能作为例子,是不能够正式的使用的。它漏掉了很关键的一个问题:当有多个用户同时像文件写入数据是,肯定会有错误发生。而对于一个这样的程序而言,文件被同时写入的几率是很大的。因此,在比较正式的留言版程序中,都需要做一些更多的考虑,比如加入一个信号量,或者是借助于一个钥匙文件等。因为那只是编程的技巧问题,在这儿就不多说了。
下面是仅查看文件../data/data.txt的C源代码:
#include#include #define DATAFILE "../data/data.txt" int main(void) { FILE *f = fopen(DATAFILE,"r"); int ch; if(f == NULL) { printf("%s%c%c\n", "Content-Type:text/html;charset=iso-8859-1",13,10); printf(" Failure \n"); printf("Unable to open data file, sorry!"); } else { printf("%s%c%c\n", "Content-Type:text/plain;charset=iso-8859-1",13,10); while((ch=getc(f)) != EOF) putchar(ch); fclose(f); } return 0; } 相应的html表单:
-----------------------------------------------
附:get方式分离表单m和表单n的数据。
#include#include main() { char *qa; int m1,n1; printf("%s%c%c\n","Content-Type:text/html;charset=GB2312",13,10); printf(" 表单内容返回 \n"); qa = getenv ("QUERY_STRING"); sscanf(qa,"m=%d&n=%d",&m1,&n1); printf("%d,%d",m1,n1); return 0; }
附2:post方式获取表单m和表单n的数据。
#include#include #define MAXLEN 80 #define EXTRA 5 /* 4个字节给字段"data", 1个字节留给"=" */ #define MAXINPUT MAXLEN+EXTRA+2 /* 1个字节留给换行符,还有一个留给后面的NULL */ //#define DATAFILE "./haha.sh" /* 要被添加数据的文件 */
int main(void) { long len; char *lenstr,poststr[20]; char m[10],n[10]; printf("%s%c%c\n","Content-Type:text/html;charset=GB2312",13,10); printf("我的cgi返回结果 \n"); lenstr = getenv("CONTENT_LENGTH"); //if(lenstr == NULL || len > MAXLEN) if(lenstr == NULL) printf("表单提交错误."); else{ len = atoi(lenstr); fgets(poststr,len+1,stdin); if (sscanf(poststr,"m=%[^&]&n=%s",m,n)!=1) {printf("m=%s,n=%s\n",m,n);} printf("");} return 0; }