题记:用“易语言.飞扬”(EF)开发WEB应用程序,此前还没有先例。但因为EF本地开发包(EFNDK)已经发布,用C/C++开发一个EF类库,使其支持EF开发WEB应用程序,应该并非难事。当然也可想而知,其中必有诸多难点有待解决。此系列文章,为本人探索过程之记录,对外人未必有多大价值。如有网友乐观其事,还请理性待之。作者:liigo。转载请务必注明出处:http://blog.csdn.net/liigo/。在线留言。
试用EF开发WEB应用程序(5): URL编码和URL解码
之前的文章提到,Query String是URL的一部分,那么其内容应当遵守URL的语法规则,例如不能出现 ; / ? = & 等特定字符,也不应该包含汉字字符。通常,在需要组合生成一个URL时,需要对Query String中的内容(尤其是value部分)进行“URL编码”,以确保得到一个合法的URL;在处理一个URL请求时,需要对Query String进行“URL解码”,以便还原到“URL编码”之前的Query String。CGI / FastCGI 程序在处理HTTP请求时,其从环境变量 QUERY_STRING 中获取的内容,即为已经过“URL编码”的Query String。
以之前文章中出现的URL “http://localhost:8080/querystring.efcgi?x=abc&y=ef&z=%E4%B8%AD%E5%9B%BD” 为例,其中“%E4%B8%AD%E5%9B%BD” 部分就是“URL编码”后的结果,经过“URL解码”之后,是汉字“中国”二字。
考虑到“URL编码”和“URL解码”是常见操作,EF类库 fastcgi.efn 中提供了这两项功能,同时对环境变量 QUERY_STRING 中的内容自动进行“URL解码”。
在EF类库 fastcgi.efn 中,实现“URL编码”的C++代码如下:
EFChar
*
URLEncode(EFChar
*
url,EF_MiniMem
&
buffer)
{
EFCharc;
EFCharhexOutputBuffer[
2
];
EF_MiniMemmem;
int
n
=
EF_strlen(url);
buffer.Alloc(n
<<
1
);
buffer.Empty();
for
(
int
i
=
0
;i
<
n;i
++
)
{
c
=
url[i];
if
((c
>=
'
a
'
&&
c
<=
'
z
'
)
||
(c
>=
'
0
'
&&
c
<=
'
9
'
)
||
(c
>=
'
A
'
&&
c
<=
'
Z
'
)
||
(strchr(
"
-_.
"
,c)
!=
NULL))
{
buffer.AddChar(c);
}
else
if
(c
==
'
'
)
{
buffer.AddChar(myC(
'
+
'
));
}
else
{
if
(c
<=
255
)
{
_URLEncode_addEncodeChar((unsigned
char
)c,buffer,hexOutputBuffer);
}
else
{
const
char
*
utf8
=
(
const
char
*
)EF_UCS_to_UTF8(
&
c,
1
,mem);
int
len
=
strlen(utf8);
for
(
int
j
=
0
;j
<
len;j
++
)
{
_URLEncode_addEncodeChar(utf8[j],buffer,hexOutputBuffer);
}
}
}
}
buffer.AddChar(myC(
'
在EF中,调用 FCGI.URLEncode() 即可进行“URL编码”工作。
在EF类库 fastcgi.efn 中,实现“URL解码”的C++代码如下:
EFChar
*
URLDecode(EFChar
*
url,EF_MiniMem
&
buffer)
{
EFCharc,
*
pc;
unsigned
char
utf8[
3
];
EF_MiniMemmem;
int
n
=
EF_strlen(url);
buffer.Alloc(n);
buffer.Empty();
for
(
int
i
=
0
;i
<
n;i
++
)
{
c
=
url[i];
if
(c
!=
myC(
'
%
'
))
{
buffer.AddChar((c
==
myC(
'
+
'
)
?
myC(
'
'
):c));
continue
;
}
utf8[
0
]
=
fromhex(
&
url[i
+
1
]);
if
((utf8[
0
]
&
0x80
)
==
0
)
//
0xxxxxxx
{
buffer.AddChar((EFChar)utf8[
0
]);
i
+=
2
;
}
else
if
((utf8[
0
]
>>
5
)
==
6
)
//
110xxxxx
{
if
(n
-
i
>=
6
&&
url[i
+
3
]
==
myC(
'
%
'
))
{
utf8[
1
]
=
fromhex(
&
url[i
+
4
]);ASSERT(utf8[
1
]
>>
6
==
2
);
//
10xxxxxx
pc
=
EF_UTF8_to_UCS((
char
*
)utf8,
2
,mem);
ASSERT(pc
&&
EF_strlen(pc)
==
1
);
if
(pc
==
NULL)
return
NULL;
buffer.AddChar(
*
pc);
i
+=
5
;
}
else
return
NULL;
}
else
if
((utf8[
0
]
>>
4
)
==
0x0E
)
//
1110xxxx
{
if
(n
-
i
>=
9
&&
url[i
+
3
]
==
myC(
'
%
'
)
&&
url[i
+
6
]
==
myC(
'
%
'
))
{
utf8[
1
]
=
fromhex(
&
url[i
+
4
]);ASSERT(utf8[
1
]
>>
6
==
2
);
//
10xxxxxx
utf8[
2
]
=
fromhex(
&
url[i
+
7
]);ASSERT(utf8[
2
]
>>
6
==
2
);
//
10xxxxxx
pc
=
EF_UTF8_to_UCS((
char
*
)utf8,
3
,mem);
ASSERT(pc
&&
EF_strlen(pc)
==
1
);
if
(pc
==
NULL)
return
NULL;
buffer.AddChar(
*
pc);
i
+=
8
;
}
else
return
NULL;
}
else
return
NULL;
}
buffer.AddChar(myC(
'
在EF中,调用 FCGI.URLDecode() 即可进行“URL解码”工作。
网络浏览器在处理用户提交的FORM数据时,也会自动将FORM中的数据生成经过“URL编码”的Query String。在实践中发现,如果FORM所属HTML文件的编码为UTF-8,则汉字是按其UTF-8编码数据进行“URL编码”;如果FORM所属HTML文件的编码未指定或为非UTF-8编码,则汉字可能不是按其UTF-8编码数据进行“URL编码”。本文上面所列代码,只能按UTF-8编码进行“URL编码”和“URL解码”,使用时需要注意。
如果代码有错误或疏忽、遗漏之处,请各位批评指正。
下文预告:解析Query String中的各参数值