解码URL中的变音符号(或复合与预编译编码)

时间:2015-03-11 21:43:52

标签: http winapi unicode utf-8 url-encoding

我的申请处理网址。

以下是一个例子:

https://127.0.0.1/Datei_Verz ._Änderung.gif

浏览器发送的是:

https://127.0.0.1/Datei_Verz._%C3%84nderung.gif

当未转义时(使用AtlUnescapeUrl),%C3和%84被视为不同的字符,因此我最终得到:

https://127.0.0.1/Datei_Verz ._ A“nderung.gif

因此,unescape无法识别浏览器发送复合字符而不是预先组合(使用MSDN中的解释)。

理想情况下,浏览器会用单个Unicode代码点LATIN CAPITAL LETTER A WITH DIAERESIS(U + 00C4)代表Ä,我认为它可能是URL中的%00C4。

那么如何解码初始URL?

1 个答案:

答案 0 :(得分:4)

这与Unicode规范化(预合成字符与分解字符序列)无关。这只是一个错误的字节编码的情况。

  

理想情况下,浏览器会用单个Unicode代码点LATIN CAPITAL LETTER A WITH DIAERESIS(U + 00C4)代表Ä,我认为它可能是URL中的%00C4。

不:URL编码是基于字节的编码; %-escape严格是两位数(一个字节),因此%00C4将是一个零字节,后跟文字字符C4

没有%-encoding覆盖一个具有单个转义序列的代码点。在转义为%nn序列之前,必须将Unicode URL组件编码为字节。

对于基于ISO-8859-1或代码页1252的Web应用程序,

%C4将是Ä的编码,但是大多数Web应用程序今天使用的编码(并且由IRI强制执行)标准)是UTF-8。 %C3%84是UTF-8中Ä的正确编码。

不幸的是,在IRI出现之前,ATL是一个令人伤心的旧图书馆。当它看到非ASCII转义序列时,它会使用您机器的特定于语言环境的默认(ANSI)代码页将它们解码为Unicode,该代码页永远不会是UTF-8。对于西欧Windows安装,您可以获得代码页1252,其中%C3%84表示两个字符Ä

(这可能是一个错误。在atlutil.h的版本中,我必须提到前面的评论说无论使用什么编码都没关系,因为没有非ASCII字符,这是真的对于上面AtlEscapeUrl中的代码,它不经意地被复制粘贴,但对于AtlUnescapeUrl来说根本不是真的。这似乎意味着ATL转义和unescape函数不使用相同的编码和所以不要往返......哎呀。)

要解决此问题,您可以自己执行Unicode位。而不是调用AtlUnescapeUrl的Unicode(LPWSTR)版本,使用UTF-8编码(MultiByteToWideChar CP_UTF8)将输入的Unicode字符串转换为字节字符串,然后调用{的字节(LPSTR)版本{ {1}}在字节字符串上,再次解码(AtlUnescapeUrl CP_UTF8)。

或者选择另一个较少损坏的URL处理库。