HttpUtility.HtmlEncode не кодирует все - PullRequest
16 голосов
/ 13 февраля 2009

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

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

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

Ответы [ 7 ]

13 голосов
/ 14 февраля 2009

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

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

 HttpUtility.HtmlEncode(outgoingString, Response.Output);

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

12 голосов
/ 14 февраля 2009

Рич Штраль только что опубликовал сообщение в блоге, 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();
}
11 голосов
/ 14 февраля 2009

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

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();
}
3 голосов
/ 14 апреля 2011

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

AntiXSS на Codeplex

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

2 голосов
/ 23 мая 2010

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

1 голос
/ 12 июня 2011
Ответ

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

/// <summary>.Net 2.0's 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;
}
0 голосов
/ 20 мая 2016

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

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

string encoded = HttpUtility.HtmlEncode(text);
if(encoded.Contains("&#39;"))
{
    encoded = encoded.Replace("&#39;", "'");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...