2009-02-13 10 views
14

estoy interactuando con un servidor web utilizando un programa cliente de escritorio en C# y .Net 3.5. Estoy usando Fiddler para ver qué tráfico envía el navegador web y emular eso. Lamentablemente, este servidor es viejo, y está un poco confundido acerca de las nociones de conjuntos de caracteres y utf-8. Sobre todo usa Latin-1.HttpUtility.HtmlEncode no codifica todo

Cuando introducir datos en el navegador Web que contienen caracteres "especiales", así como "Ω π ℵ ∞ ♣ ♥ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓" violinista me muestran que están siendo transmitidos de la siguiente del navegador al servidor: "♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ "

Pero para mi cliente, HttpUtility.HtmlEncode no convierte estos caracteres, los deja como están. ¿Qué necesito para llamar a convertir "♈" a & # 9800; ¿y así?

+0

Extrañamente, .Net 2.0 de HttpUtility codificará adecuadamente los caracteres entre 0xA0 y 0xFF, pero no los de arriba (Compruébelo usted mismo.! utilizando reflector.) –

+0

extraño. HttpUtility.HtmlEncode (todas las sobrecargas) HttpEncoder.Current.HtmlEncode llamar, por lo que parece que el codificador utilizado depende el valor de HttpEncoder.Current, respecto del cual: "Si se especifica un tipo de HttpEncoder derivado en el archivo de configuración, la propiedad Current devuelve una referencia al tipo personalizado. Sin embargo, si no se utiliza un codificador personalizado, la propiedad devuelve una referencia a la instancia predeterminada de HttpEncoder de ASP.NET.La propiedad Current no es segura para subprocesos. Establezca esta propiedad solo en el método Application_Start de la aplicación, porque Application_Start se ejecuta en un único hilo. " – Triynko

+5

Creo que la razón de esto es que esos caracteres no son ilegales si el conjunto de caracteres especificado para el documento lo permite. HtmlEncode está destinado a eliminar peligros caracteres, no codifica todos los caracteres que podrían codificarse. La letra A también puede codificarse así, pero no es necesario. – TheXenocide

Respuesta

8

Parece terriblemente ineficiente, pero la única manera que puedo pensar de hacerlo es mirar a través de cada personaje:

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(); 
} 
+0

Esto funciona. No he probado los otros todavía. – Anthony

+0

'Server.HtmlEncode' y' HttpUtility.HtmlEncode' no codificarían [este carácter: '] (http://www.fileformat.info/info/unicode/char/2019/index.htm), pero esta solución funcionó . – Pluto

+0

Esto podría fallar para pares de sustitución como [GRINNING FACE] (http://www.fileformat.info/info/unicode/char/1f600/index.htm). Es posible que necesite usar métodos de alguna manera como [Char.IsHighSurrogate] (http://msdn.microsoft.com/en-us/library/xcwwfbb8 (v = vs.110) .aspx). –

12

Rich Strahl acaba de publicar una entrada de blog, Html and Uri String Encoding without System.Web, donde tiene un código personalizado que codifica el rango superior de caracteres, también.

/// <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(); 
} 
+0

¿Qué razones existen para codificar HTML sin System.Web? – AnthonyWJones

+5

¿Por qué 159 para el corte? – Anthony

+1

Te estás olvidando de la comilla simple '''. ¡Codifica eso! '' –

13

El valor de retorno tipo de HtmlEncode es una cadena, que es de Unicode y por lo tanto no tiene necesidad de codificar estos caracteres.

Si la codificación de la secuencia de salida no es compatible con estos caracteres a continuación, utilizar HtmlEncode así: -

HttpUtility.HtmlEncode(outgoingString, Response.Output); 

HtmlEncode con el entonces escapar los caracteres de manera apropiada.

+0

Interesante, pero ¿cómo lo vincularías con la técnica de publicación de Scott H en http://www.hanselman.com/blog/PermaLink.aspx?guid=43e49ec8-1fa7-44c1-8177-42cd4fead8db – Anthony

+0

@Anthony: No lo hacen t atar para nada (¿publicaste el enlace correcto?). HtmlEncode no tiene nada que ver con las emulaciones de formulario POST, o estabas pensando en cosas de URLEncode, eso es algo diferente. – AnthonyWJones

+0

@ AnthonyWJones sí, es el enlace correcto para la técnica de publicación. Debo codificar de esta manera antes de publicar el formulario. – Anthony

2

Parece que HtmlEncode es sólo para cadenas de codificación que se ponen en documentos HTML, donde sólo/<> & etc. causan problemas. Para las URL, simplemente reemplace HtmlEncode con UrlEncode.

+0

No, UrlEncode también es horrible. Por ej. + no se convierte a% 2b. – arviman

3

biblioteca La AntiXSS de Microsoft codifica correctamente estos caracteres.

AntiXSS on Codeplex

Nuget package (mejor manera de agregar como referencia)

+0

Tenga en cuenta que todavía existe una gran diferencia, mientras que HttpUtility.UrlEncode codifica correctamente ÄÖÜß, AntiXssEncoder no, a menos que desee entidades con nombre. – CSharpie

+0

Esta biblioteca tiene un mal hábito de destruir personajes emoji, como. –

1

@bdukes respuesta anterior hará el trabajo, pero podemos hacer que sea mucho más rápido si asumimos que la mayoría de los personajes no ser en este rango Tenga en cuenta la 'A' citado (0x0100 Unicode)

/// <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

Siempre se puede sustituir el ASCII no deseada de la siguiente manera: Cuando esto se codifica sin la instrucción if la cadena resultado es "Esto significa que estoy llorando: '&' # 39;) Por la razón que se manejan y se sustituye 'caracteres especiales' con carbón HTML

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

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