如何在C中使用unicode正确解码url

时间:2017-02-12 22:27:48

标签: c unicode utf-8 urldecode

在我的推荐人日志中,我正在尝试解码引荐来源,但看起来%81%8A的编码百分比无效,因此我得到了ri�0�9o

我需要通过websocket发送已解码的字符串,现在我在浏览器端获得Could not decode a text frame as UTF-8.

这些甚至是有效的百分比编码吗?我怎么知道它们是否有效?

#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>

void urldecode2(char *dst, const char *src) {
    char a, b;
    while(*src) {
        if((*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {
            if(a >= 'a')
                a -= 'a'-'A';
            if(a >= 'A')
                a -= ('A' - 10);
            else
                a -= '0';
            if(b >= 'a')
                b -= 'a'-'A';
            if(b >= 'A')
                b -= ('A' - 10);
            else
                b -= '0';
            *dst++ = 16*a+b;
            src+=3;
        } else if(*src == '+') {
            *dst++ = ' ';
            src++;
        } else {
            *dst++ = *src++;
        }
    }
    *dst++ = '\0';
}

int main () {
    const char *in = "http://www.google.co.in/search?q=cari%810%8A9o";
    char out[100];

    urldecode2(out, in);
    printf("%s\n", out);

    return 0;
}

1 个答案:

答案 0 :(得分:2)

%81%8A完全有效%-escapes,但结果不是UTF-8字符串。 URL不需要是UTF-8字符串,但现在它们通常都是。

在我看来,发生了一些非常奇怪的双重编码。我不知道哪个使用三位数的%-encodings,但这就是你在该URL中的样子。假设意图是对西班牙语单词“cariño”(照顾,感情,喜爱)进行编码,它应该是cari%C3%B1o的UTF-8,或cari%F1o的ISO-8859-1 / Windows-1252(通常意外地显示在URL中)。

有效UTF-8序列的规则非常简单,您可以使用正则表达式检查有效序列。并非所有有效序列都映射到字符,其中66个被明确映射为“非字符”,但所有有效序列都应该由符合标准的解码器接受,即使它稍后拒绝解码后的字符在语义上不正确。

UTF-8序列是对应于以下模式之一的一到四字节序列:(取自Unicode标准,表3.7)

    Byte 1      Byte 2      Byte 3      Byte 4
    ------      ------      ------      ------
    00..7F        --          --          --
    C2..DF      80..BF        --          --
    E0          A0..BF      80..BF        --
    E1..EC      80..BF      80..BF        --
    ED          80..9F      80..BF        --
    EE..EF      80..BF      80..BF        --
    F0          90..BF      80..BF      80..BF
    F1..F3      80..BF      80..BF      80..BF
    F4          80..8F      80..BF      80..BF

其他任何事情都是非法的。 (因此,代码C0,C1和F5到FF根本不会出现。)特别是,十六进制代码81和8A永远不能启动UTF-8序列。

由于没有好的方法可以知道无效序列的含义,最简单的方法就是将它们剥离出去。