http://blog.163.com/pirates_fish/blog/static/1833331502011423111941498/

我们来看看到底如何从POST表单收集数据到CGI程序,下面给出了一個比较简单的C源代码:      

#include <stdio.h>
#include <stdlib.h>
#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("<TITLE>Response</TITLE>\n");
lenstr = getenv("CONTENT_LENGTH");
if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
  printf("<P>表单提交错误.");
else {
  FILE *f;
  fgets(input, len+1, stdin);
  unencode(input+EXTRA, input+len, data);
  f = fopen(DATAFILE, "a");
  if(f == NULL)
    printf("<P>对不起,意外错误,不能够保存你的数据.");
  else
    fputs(data, f);
  fclose(f);
  printf("<P>非常感谢,您的数据已经被保存!<BR>%s",data);
  }
return 0;
}
      从本质上来看,程序先从CONTENT_LENGTH环境变量中得到数据的字长,然后读取相应长度的字符串。因为数据内容在传输的过程中是经过了编码的,所以必须进行相应的解码。编码的规则很简单,主要的有这几条:     

1.   表单中每个每个字段用字段名后跟等号,再接上上这个字段的值来表示,每个字段之间的内容用&连结;

2.   所有的空格符号用加号代替,所以在编码码段中出现空格是非法的;     
       3.   特殊的字符比如标点符号,和一些有特定意义的字符如“+”,用百分号后跟其对应的ACSII码值来表示。     

例如:如果用户输入的是:     
                 Hello   there!     
那么数据传送到服务器的时候经过编码,就变成了data=Hello+there%21   上面的unencode()函数就是用来把编码后的数据进行解码的。在解码完成后,数据被添加到data.txt文件的尾部,并在浏览其中回显出来。     
把文件编译完成后,把它改名为mult.cgi后放在CGI目录中就可以被表单调用了。

gcc -o mult.cgi mult.c

下面给出了其相应的html表单:     

<form action="/cgi-bin/mult.cgi" method="post">
<div>
请输入您的留言(最多80个字符
):<br>
<input name="data" size="60" maxlength="80"><br>
<input type="submit" value="Send"></div>
</form>

   


注意:  ../data/data.txt的文件应该提前建立,而且文件属性应该为666.

chmod 666 ../data/data.txt    
    
       事实上,这个程序只能作为例子,是不能够正式的使用的。它漏掉了很关键的一个问题:当有多个用户同时像文件写入数据是,肯定会有错误发生。而对于一个这样的程序而言,文件被同时写入的几率是很大的。因此,在比较正式的留言版程序中,都需要做一些更多的考虑,比如加入一个信号量,或者是借助于一个钥匙文件等。因为那只是编程的技巧问题,在这儿就不多说了。

下面是仅查看文件../data/data.txt的C源代码:

#include <stdio.h>
#include <stdlib.h>
#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("<TITLE>Failure</TITLE>\n");
  printf("<P><EM>Unable to open data file, sorry!</EM>"); }
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表单:
<form action="/cgi-bin/viewdata.cgi">
<div><input type="submit" value="View"></div>
</form>
-----------------------------------------------
附:get方式分离表单m和表单n的数据。
#include <stdio.h>
#include <stdlib.h>
main()
{
char *qa;
int m1,n1;
printf("%s%c%c\n","Content-Type:text/html;charset=GB2312",13,10);
printf("<TITLE>表单内容返回</TITLE>\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 <stdio.h>
#include <stdlib.h>
#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("<TITLE>我的cgi返回结果</TITLE>\n");
lenstr = getenv("CONTENT_LENGTH");
//if(lenstr == NULL || len > MAXLEN)
if(lenstr == NULL)
  printf("<P>表单提交错误.");
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("<input type=\"button\" value=\"Back CGI\" οnclick=\"javascript:window
.location='../../ip.html'\">");}
return 0;
}
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐