从POST(CGI和C)取消编码数据

时间:2014-08-16 19:13:02

标签: c post cgi

我刚刚阅读本页http://www.cs.tut.fi/~jkorpela/forms/cgic.html关于在C中开始使用CGI。我对未编码部分的代码有疑问。

#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 80
#define EXTRA 5
/* 4 for field name "data", 1 for "=" */
#define MAXINPUT MAXLEN+EXTRA+2
/* 1 for added line break, 1 for trailing NUL */
#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=iso-8859-1",13,10);
printf("<TITLE>Response</TITLE>\n");
lenstr = getenv("CONTENT_LENGTH");
if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
  printf("<P>Error in invocation - wrong FORM probably.");
else {
  FILE *f;
  fgets(input, len+1, stdin);
  unencode(input+EXTRA, input+len, data);
  f = fopen(DATAFILE, "a");
  if(f == NULL)
    printf("<P>Sorry, cannot store your data.");
  else
    fputs(data, f);
  fclose(f);
  printf("<P>Thank you! Your contribution has been stored.");
  }
return 0;
}

我想知道这些线是怎么回事:

else if(*src == '%') {
     int code;
     if(sscanf(src+1, "%2x", &code) != 1) code = '?';
     *dest = code;
     src +=2; }    

将%21之类的内容转换回感叹号?

谢谢!

2 个答案:

答案 0 :(得分:1)

else if(*src == '%') {
  int code;
  if(sscanf(src+1, "%2x", &code) != 1) code = '?';
  *dest = code;
  src +=2;
}

如果字符串以%字符开头,sscanf()用于解析以下十六进制字符。 "%x"格式将十六进制字符转换为整数值(在本例中为字符代码),2指定最大字段宽度,以便最多消耗 2个字符。

sscanf()的返回值表示成功转换的次数,因此如果它不返回1,则找不到有效的十六进制数。

然后将字符代码分配给*dest,并将src指针提前指向%xx序列之后的下一个字符。

这里实际上有三个错误:

  1. "%x"格式说明符需要unsigned int *类型的参数。传递了signed int *,我相信,它会调用未定义的行为。变量函数(例如sscanf())具有传递参数的不同方式,并且要求格式说明符与参数的类型匹配。

    然而,这两种类型足够相似,在实践中可能会很好。

  2. 它还接受签名的十六进制数字(带有+-字符),这可能不是作者想要的。

    例如,"%-ffText"会产生code == -15

  3. src指针前进2个字节,但scanf()不一定消耗2个字符。

    "%fText"将导致code == 15,并且只消耗一个字符(%字符除外)。上面的示例将消耗3个字符。

答案 1 :(得分:0)

sscanf函数将2个十六进制字符转换为单个int值。该值等于ASCII值,因此放入&#39; dest&#39;。由于已经解码了2个字符,因此src必须增加两个位置。 所以&#39;%21&#39; - &GT; 0x21 - &gt; char&#39;!&#39;