这几天在用C语言实现一个轻量级 CGI Server,还差一小部分就完成了,昨天晚上在实现URL Decode功能,怎么也实现不了,当时感觉累了,智商就跟不上了,今天起床后,重新实现了该部分代码,发现是我对URL 编码和解码部分理解不够深入,这里记录下。
我这里简单说下原理,不懂的看下参考资料里的详细解释,URL链接里的中文是以UTF-8编码的,URL 链接里的编码规则为:
- 将空格转换为加号(+)。
- 对0-9,a-z,A-Z之间的字符保持不变。
- 对于所有其他的字符,用这个字符的当前字符集编码在内存中的十六进制格式表示,并在每个字节前加上一个百分号(%)。如字符“+”用%2B表示,字符“=”用%3D表示,字符“&”用%26表示,而“我爱你中国”用%e6%88%91%e7%88%b1%e4%bd%a0%e4%b8%ad%e5%9b%bd表示。
所以,对于%e4%b8%ad我们想解码的话,只需要把e4 b8 ad 各字符分别转换为对应的二进制即可,即,e = 1110 4 = 0100 等等,之后组合起来,按照UTF-8编码对应的规则,即可解释出对应的中文(或其他语言),详细原理可以查看参考链接。
我们这里写下C语言实现的Encode代码,Decode我就懒的打了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| char from_hex(char ch) { return isdigit(ch) ? ch - '0': tolower(ch) - 'a' + 10; } int main() { char *url = "%e6%88%91%e7%88%b1%e4%bd%a0%e4%b8%ad%e5%9b%bd"; printf("%s\n",url); if(strstr(url,"%")) { char *buf = malloc(strlen(url) + 1); char *pstr = url; char *pbuf = buf; while(*pstr) { if(*pstr == '%') { if(pstr[1] && pstr[2]) { *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); pstr += 2; } } else if(*pstr == '+') { *pbuf++ = ' '; } else { *pbuf++ = *pstr; } pstr++; } *pbuf = '\0'; printf("%s\n",buf); free(buf); } return 0; }
|
结果输出为:
%e6%88%91%e7%88%b1%e4%bd%a0%e4%b8%ad%e5%9b%bd
我爱你中国
参考链接:
http://www.ruanyifeng.com/blog/2010/02/url_encoding.html
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html