9

MSDN ごと

URLEncode は次のように文字を変換します。

  • スペース ( ) はプラス記号 (+) に変換されます。
  • 英数字以外の文字は、16 進数表現にエスケープされます。

これは似ていますが、 W3Cとまったく同じではありません

application/x-www-form-urlencoded

これはデフォルトのコンテンツ タイプです。このコンテンツ タイプで送信されるフォームは、次のようにエンコードする必要があります。

  1. コントロールの名前と値はエスケープされます。スペース文字は「+」に置き換えられ、予約文字はRFC1738のセクション 2.2 で説明されているようにエスケープされます。英数字以外の文字は、「%HH」、パーセント記号、および文字の ASCII コードを表す 2 桁の 16 進数に置き換えられます。改行は "CR LF" のペア (つまり、'%0D%0A') として表されます。

  2. コントロールの名前/値は、ドキュメントに表示される順序でリストされています。名前と値は「=」で区切られ、名前と値のペアは「&」で区切られます。

 

私の質問は、URLEncode が有効な x-www-form-urlencoded データを生成するかどうかを判断する作業を行った人はいますか?

4

1 に答える 1

6

リンク先のドキュメントは IIS 6 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 セーフでない文字) をカウントします。ルーチンの 2 番目の部分は、新しいバッファーを割り当て、置換を実行します。

  1. URL セーフ文字はそのまま保持されます。a-z A-Z 0-9 ()*-._!
  2. スペースはプラス記号に変換されます
  3. 他のすべての文字は%HH

RFC1738 の状態 (強調鉱山):

したがって、英数字、特殊文字「$-_.+!*'()」、および
予約された目的で使用される予約文字のみ が、URL 内でエンコードされずに使用できます。

一方、エンコードする必要のない文字 (英数字を含む) は 、予約された目的で使用されていない限り、URL
のスキーム固有の部分内でエンコードできます 。

で許可されている URL セーフ文字のセットはUrlEncode、RFC1738 で定義されている特殊文字のサブセットです。つまり、文字$,が欠落しておりUrlEncode、仕様で安全とされていても によってエンコードされます。それらはエンコードされずに使用される可能性があるため (そしてmustではない)、それらをエンコードする仕様を満たしています (そして 2 番目の段落で明示的に述べられています)。

改行に関しては、入力にCR LFシーケンスがある場合、それはエスケープされ%0D%0Aます。ただし、入力にLFそれしかない場合はエスケープされます%0A(したがって、このルーチンでは改行の正規化は行われません)。

結論:を追加でエンコードしながら仕様を満たし、$,呼び出し元は入力に適切に正規化された改行を提供する責任があります。

于 2011-09-16T18:55:47.577 に答える