HttpUtility.HtmlEncode не кодирует все

Я взаимодействую с веб-сервером с помощью клиентской клиентской программы на С# и .Net 3.5. Я использую Fiddler, чтобы посмотреть, какой трафик веб-браузер отправляет, и подражать этому. К сожалению, этот сервер устарел и немного запутался в понятиях кодировок и utf-8. В основном он использует Latin-1.

Когда я ввожу данные в веб-браузер, содержащий "специальные" символы, например "Ω π ℵ ∞ ♣ ♥ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ "скрипач показать мне, что они передаются следующим образом из браузера на сервер: "♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ "

Но для моего клиента HttpUtility.HtmlEncode не преобразует эти символы, он оставляет их как есть. Что мне нужно, чтобы позвонить, чтобы преобразовать "♈" в & # 9800; и так далее?

Ответы

Ответ 1

Кажется ужасно неэффективным, но единственный способ, которым я могу это сделать, - просмотреть каждый символ:

public static string MyHtmlEncode(string value)
{
   // call the normal HtmlEncode first
   char[] chars = HttpUtility.HtmlEncode(value).ToCharArray();
   StringBuilder encodedValue = new StringBuilder();
   foreach(char c in chars)
   {
      if ((int)c > 127) // above normal ASCII
         encodedValue.Append("&#" + (int)c + ";");
      else
         encodedValue.Append(c);
   }
   return encodedValue.ToString();
}

Ответ 2

Тип возвращаемого значения HtmlEncode - это строка, которая имеет Unicode и, следовательно, не нуждается в кодировании этих символов.

Если кодировка вашего выходного потока несовместима с этими символами, используйте HtmlEncode следующим образом: -

 HttpUtility.HtmlEncode(outgoingString, Response.Output);

HtmlEncode с последующим выводом символов соответствующим образом.

Ответ 3

Rich Strahl только что разместил сообщение в блоге, Html и Uri String Encoding без System.Web, где у него есть собственный код, который кодирует верхний диапазон символов тоже.

/// <summary>
/// HTML-encodes a string and returns the encoded string.
/// </summary>
/// <param name="text">The text string to encode. </param>
/// <returns>The HTML-encoded text.</returns>
public static string HtmlEncode(string text)
{
    if (text == null)
        return null;

    StringBuilder sb = new StringBuilder(text.Length);

    int len = text.Length;
    for (int i = 0; i < len; i++)
    {
        switch (text[i])
        {

            case '<':
                sb.Append("&lt;");
                break;
            case '>':
                sb.Append("&gt;");
                break;
            case '"':
                sb.Append("&quot;");
                break;
            case '&':
                sb.Append("&amp;");
                break;
            default:
                if (text[i] > 159)
                {
                    // decimal numeric entity
                    sb.Append("&#");
                    sb.Append(((int)text[i]).ToString(CultureInfo.InvariantCulture));
                    sb.Append(";");
                }
                else
                    sb.Append(text[i]);
                break;
        }
    }
    return sb.ToString();
}

Ответ 4

Библиотека AntiXSS от Microsoft правильно кодирует эти символы.

AntiXSS на Codeplex

пакет Nuget (лучший способ добавить в качестве ссылки)

Ответ 5

Кажется, что HtmlEncode предназначен только для кодирования строк, которые помещаются в HTML-документы, где только /< > и т.д. вызывают проблемы. Для URL-адресов просто замените HtmlEncode на UrlEncode.

Ответ 6

Ответ на

@bdukes выше выполнит эту работу, но мы можем сделать это намного быстрее, если предположить, что большинство символов не будут в этом диапазоне. Обратите внимание на цитируемый 'À' (unicode 0x0100)

/// <summary>.Net 2.0 HttpUtility.HtmlEncode will not properly encode
/// Unicode characters above 0xFF.  This may be fixed in newer 
/// versions.</summary>
public static string HtmlEncode(string s)
{
    // Let .Net 2.0 get right what it gets right.
    s = HttpUtility.HtmlEncode(s);

    // Search for first non-ASCII.  Hopefully none and we can just 
    // return s.
    int num = IndexOfHighChar(s, 0);
    if (num == -1)
        return s;
    int old_num = 0;
    StringBuilder sb = new StringBuilder();
    do {
        sb.Append(s, old_num, num - old_num);
        sb.Append("&#");
        sb.Append(((int)s[num]).ToString(NumberFormatInfo.InvariantInfo));
        sb.Append(';');
        old_num = num + 1;
        num = IndexOfHighChar(s, old_num);
    } while (num != -1);
    sb.Append(s, old_num, s.Length - old_num);
    return sb.ToString();
}

static unsafe int IndexOfHighChar(string s, int start)
{
    int num = s.Length - start;
    fixed (char* str = s) {
        char* chPtr = str + start;
        while (num > 0) {
            char ch = chPtr[0];
            if (ch >= 'Ā')
                return s.Length - num;
            chPtr++;
            num--;
        }
    }
    return -1;
}

Ответ 7

Вы всегда можете заменить нежелательный ASCII следующим образом: когда это закодировано без оператора if, строка результата: "Это означает, что я плачу: '&' # 39;) По какой-либо причине обрабатываются" специальные символы "и заменен на HTML char.

string text = "This means I am crying :'(";

string encoded = HttpUtility.HtmlEncode(text);
if(encoded.Contains("&#39;"))
{
    encoded = encoded.Replace("&#39;", "'");
}