代码之家  ›  专栏  ›  技术社区  ›  hemp

HttpUtility.UrlEncode是否与“x-www-form-urlencoded”的规范匹配?

  •  9
  • hemp  · 技术社区  · 14 年前

    Per MSDN

    URLEncode按如下方式转换字符:

    • 非字母数字字符转义为其十六进制表示形式。

    W3C

    应用程序/x-www-form-urlencoded

    这是默认的内容类型。使用此内容类型提交的表单必须编码如下:

    1. 控件名称和值被转义。替换空格字符 按“+”,然后按保留字符 如中所述逃逸 RFC1738 第2.2节:非字母数字 字符替换为“%HH”,a 表示的ASCII码的数字 角色。换行符是 “%0D%0A”)。

    2. 控件名称/值按它们在 文件。名称与 值由“=”和名称/值对组成 以“&分隔”。

    我的问题是,有没有人做过确定URLEncode是否生成有效的x-www-form-urlencoded数据的工作?

    1 回复  |  直到 14 年前
        1
  •  6
  •   Michael Petito    13 年前

    好吧,您链接到的文档是针对iis6 Server.UrlEncode的,但是您的标题似乎是关于.NET的 System.Web.HttpUtility.UrlEncode . 使用类似Reflector的工具,我们可以看到后者的实现,并确定它是否符合W3C规范。

    下面是最终被调用的编码例程(注意,它是为字节数组定义的,而其他采用字符串的重载最终会将这些字符串转换为字节数组并调用此方法)。您可以为每个控件名称和值调用此函数(以避免转义保留字符) = &

    protected internal virtual byte[] UrlEncode(byte[] bytes, int offset, int count)
    {
        if (!ValidateUrlEncodingParameters(bytes, offset, count))
        {
            return null;
        }
        int num = 0;
        int num2 = 0;
        for (int i = 0; i < count; i++)
        {
            char ch = (char) bytes[offset + i];
            if (ch == ' ')
            {
                num++;
            }
            else if (!HttpEncoderUtility.IsUrlSafeChar(ch))
            {
                num2++;
            }
        }
        if ((num == 0) && (num2 == 0))
        {
            return bytes;
        }
        byte[] buffer = new byte[count + (num2 * 2)];
        int num4 = 0;
        for (int j = 0; j < count; j++)
        {
            byte num6 = bytes[offset + j];
            char ch2 = (char) num6;
            if (HttpEncoderUtility.IsUrlSafeChar(ch2))
            {
                buffer[num4++] = num6;
            }
            else if (ch2 == ' ')
            {
                buffer[num4++] = 0x2b;
            }
            else
            {
                buffer[num4++] = 0x25;
                buffer[num4++] = (byte) HttpEncoderUtility.IntToHex((num6 >> 4) & 15);
                buffer[num4++] = (byte) HttpEncoderUtility.IntToHex(num6 & 15);
            }
        }
        return buffer;
    }
    
    public static bool IsUrlSafeChar(char ch)
    {
        if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) || ((ch >= '0') && (ch <= '9')))
        {
            return true;
        }
        switch (ch)
        {
            case '(':
            case ')':
            case '*':
            case '-':
            case '.':
            case '_':
            case '!':
                return true;
        }
        return false;
    }
    

    例程的第一部分统计需要替换的字符数(空格和非url安全字符)。例程的第二部分分配新缓冲区并执行替换:

    1. Url安全字符保持原样: a-z A-Z 0-9 ()*-._!
    2. 空格转换为加号
    3. 所有其他字符都转换为 %HH

    因此,只有字母数字,特殊字符“$-\+!*'(),”,和
    用于保留目的的保留字符 被使用
    在URL中未编码。


    (包括字母数字)可在特定方案内编码
    URL的一部分,只要它们不用于保留
    目的。

    UrlEncode 是RFC1738中定义的特殊字符的子集。即人物 $, 缺少,将由进行编码 即使说明书上说它们是安全的。因为他们 可以 未编码使用(且 必须 ),它仍然满足编码它们的规范(第二段明确指出)。

    关于换行符,如果输入有 CR LF %0D%0A . 但是,如果输入只有 LF 那就逃走了 %0A (因此在这个例程中没有换行符的标准化)。

    在额外编码的同时满足规范要求 ,调用者负责在输入中提供适当的标准化换行符。