【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
在上一节我们看到了第一个CGI程序,该程序仅仅是为了帮助理解CGI程序如何获取客户端提交的数据,只是输出环境变量没有做任何事,在实际应用中我们需要首先解析这些数据,然后提取其中我们需要的数据(如在登录时我们需要提取用户名和密码)。
我们现在已经知道在使用GET方式时,客户端提交的数据保存在环境变量QUERY_STRING中,所以我们需要做的就是获取环境变量QUERY_STRING,然后解析其中数据。我们继续使用上一节的表单示例,稍作修改,表单中有如下内容:
用户名: <inputtype="text" name="用户名"/><br/> 密码: <inputtype="password" name="密码" /><br/><inputtype="radio" name="语言" value="English"/> English <br/><inputtype="radio" name="语言" value="Chinese"/> 简体中文 <inputtype="hidden" name="sessionid" value="1234567890"/><br/><inputtype="submit" value="登录"><br/>
使用上一节的print.cgi获取环境变量QUERY_STRING的值为:
%E7%94%A8%E6%88%B7%E5%90%8D=shallnet&%E5%AF%86%E7%A0%81=cn&%E8%AF%AD%E8%A8%80=Chinese&sessionid=1234567890
所以我们首先做的就是要从中提取客户登录信息,包括用户名用户名、密码、语言、以及隐含域sessionid。
但是我们发现“用户名”在QUERY_STRING中变为
%E7%94%A8%E6%88%B7%E5%90%8D,“密码”为%E5%AF%86%E7%A0%81,而在上一节没有使用中文时却没有相应变换,这是由于web服务器和浏览器对一些特殊字符不能正确处理,可能会导致某种误会,因此在数据传输之前,浏览器会对表单内客户输入的数据中特殊字符进行编码。在web系统中“=”分隔NAME和VALUE属性,“&”分隔不同输入数据,所以如果在表单的输入中包含这些特殊字符,这些字符也会被编码。web系统会将这些不能正确处理的特殊字符转换成它的十六进制数的形式,如“=”将会被转换成“%3D”。
以下为解析QUERY_STRING的代码:
/*该函数主要做解码工作*/
int sln_string_unescape(char **attr, const char *src, int len)
{
int pos = 0, src_pos = 0;
char escape_char;
char *p = NULL;
p = (char *)malloc(len + 1);
if (NULL == p) {
return -1;
}
while (src_pos < len) {
switch (src[src_pos]) {
case '%': /*表单属性中存放的数据中十六进制数“%HH“转换成相应的字符*/
escape_char = sln_hex2bin(src[src_pos+1]); /*sln_hex2bin() 函数负责将字符转换为其对应的ASCII码*/
escape_char <<= 4;
escape_char |= sln_hex2bin(src[src_pos+2]);
p[pos] = escape_char;
src_pos += 3;
break;
case '+': /*表单属性中有存放“+”的,则将其转换为空格*/
p[pos] = '\x20';
src_pos++;
break;
default:
p[pos] = src[src_pos];
src_pos++;
break;
}
pos++;
}
*attr = p;
return 0;
}
/*该函数解析传入的表单数据并输出解析结果*/
void sln_cgi_content_parse(char *input_content, int len)
{
char *start = NULL, *end = NULL;
char *attr = NULL, *value = NULL;
int attr_len, value_len;
start = (char *)input_content;
while ((end = strchr(start, '='))) {
*end = '\0';
attr_len = end - start;
sln_string_unescape(&attr, start, attr_len);
start = end + 1;
//if not find '&', then the last char is end
end = strchr(start, '&');
if (NULL != end) {
*end = '\0';
} else {
end = (char *)&input_content[len - 1];
}
value_len = end - start;
sln_string_unescape(&value, start, value_len);
start = end + 1;
if (end - input_content > len) {
break;
}
fprintf(stdout, "<P>NAME: %s, VALUE: %s</P>\n", attr, value);
}
}
/*输出包含解析结果的页面*/
int main(int argc, const char *argv[])
{
......
fprintf(stdout, "<HTML>\n");
fprintf(stdout, "<HEAD>\n");
fprintf(stdout, "<TITLE>CGI解析GET数据</TITLE>\n");
fprintf(stdout, "<HEAD>\n");
fprintf(stdout, "<BODY>\n");
fprintf(stdout, "<H3>以下为解析后数据</H3>\n");
sln_cgi_content_parse(data, strlen(data));
fprintf(stdout, "本网页由CGI自动生成!\n");
fprintf(stdout, "</BODY>");
fprintf(stdout, "</HTML>");
......
}
点击登录之后页面跳转: