2009-06-30 17 views

Respuesta

159

cgi.escape está bien. Se escapa:

  • < a &lt;
  • >-&gt;
  • & a &amp;

Eso es suficiente para que todo el HTML.

EDIT: Si tiene caracteres no ASCII que también quieren escapar, para su inclusión en otro documento codificado que utiliza una codificación diferente, como Craig dice, sólo tiene que utilizar:

data.encode('ascii', 'xmlcharrefreplace') 
no hacer

olvide decodificar primero data a unicode, usando la codificación que codificó.

Sin embargo, en mi experiencia ese tipo de codificación es inútil si solo trabajas con unicode todo el tiempo desde el inicio. Simplemente codifique al final la codificación especificada en el encabezado del documento (utf-8 para una compatibilidad máxima).

Ejemplo:

>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace') 
'&lt;a&gt;b&#225;&lt;/a&gt; 

También digno de mención (gracias Greg) es el parámetro adicional quotecgi.escape tomas. Con establecerlo en True, cgi.escape también escapa caracteres de comillas dobles (") para que pueda usar el valor resultante en un atributo XML/HTML.

EDIT: Tenga en cuenta que cgi.escape ya no se utiliza en Python 3.2 en favor de html.escape, que hace lo mismo excepto que quote por defecto a true.

+7

El parámetro booleano adicional de cgi.escape también se debe tener en cuenta para las comillas de escape cuando se usa texto en los valores de los atributos HTML. –

+0

Solo para estar seguro: si ejecuto todos los datos no confiables a través del 'cgi.función de escape, es suficiente para proteger contra todos los attacs XSS (conocidos) –

+0

@Tomas Sedovic: Depende de dónde coloques el texto después de ejecutar cgi.escape en él. Si se coloca en el contexto HTML raíz, entonces sí, estás completamente seguro. – nosklo

8

cgi.escape debe ser bueno para escapar de HTML en el sentido limitado de escapar de las etiquetas HTML y entidades de caracteres.

Pero también debe considerar los problemas de codificación: si el HTML que desea citar tiene caracteres que no son ASCII en una codificación particular, entonces también debe tener cuidado de representarlos con sensatez al citar. Quizás podrías convertirlos en entidades. De lo contrario, debe asegurarse de que las traducciones de codificación correctas se realicen entre el código HTML de "origen" y la página en la que está incrustado, para evitar dañar los caracteres que no sean ASCII.

6

Si desea escapar de HTML en una dirección URL:

esto probablemente no es lo que el PO quería (la pregunta no indica claramente en en qué contexto se pretende usar el escape), pero la biblioteca nativa de Python urllib tiene un método para escapar de las entidades HTML que deben incluirse en una URL de forma segura.

El siguiente es un ejemplo:

#!/usr/bin/python 
from urllib import quote 

x = '+<>^&' 
print quote(x) # prints '%2B%3C%3E%5E%26' 

Find docs here

+5

Este es el tipo incorrecto de escape; estamos buscando escapes [HTML] (http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references), en contraposición a [codificación URL] (http://en.wikipedia.org/wiki/URL_Encoding). – Chaosphere2112

+2

Sin embargo, era lo que realmente estaba buscando ;-) – Brad

2

cgi.escape extendieron

Esta versión mejora cgi.escape. También conserva espacios en blanco y nuevas líneas. Devuelve una cadena unicode.

def escape_html(text): 
    """escape strings for display in HTML""" 
    return cgi.escape(text, quote=True).\ 
      replace(u'\n', u'<br />').\ 
      replace(u'\t', u'&emsp;').\ 
      replace(u' ', u' &nbsp;') 

por ejemplo

>>> escape_html('<foo>\nfoo\t"bar"') 
u'&lt;foo&gt;<br />foo&emsp;&quot;bar&quot;' 
0

Via BeautifulSoup4:

>>> bs4.dammit import EntitySubstitution 
>>> esub = EntitySubstitution() 
>>> esub.substitute_html("r&d") 
'r&amp;d' 
2

No es la forma más fácil, pero aún sencillo. La diferencia principal del módulo cgi.escape - aún funcionará correctamente si ya tiene &amp; en su texto. Como se puede ver a partir de los comentarios a la misma:

cgi.escape versión

def escape(s, quote=None): 
    '''Replace special characters "&", "<" and ">" to HTML-safe sequences. 
    If the optional flag quote is true, the quotation mark character (") 
is also translated.''' 
    s = s.replace("&", "&amp;") # Must be done first! 
    s = s.replace("<", "&lt;") 
    s = s.replace(">", "&gt;") 
    if quote: 
     s = s.replace('"', "&quot;") 
    return s 

versión de expresiones regulares

QUOTE_PATTERN = r"""([&<>"'])(?!(amp|lt|gt|quot|#39);)""" 
def escape(word): 
    """ 
    Replaces special characters <>&"' to HTML-safe sequences. 
    With attention to already escaped characters. 
    """ 
    replace_with = { 
     '<': '&gt;', 
     '>': '&lt;', 
     '&': '&amp;', 
     '"': '&quot;', # should be escaped in attributes 
     "'": '&#39' # should be escaped in attributes 
    } 
    quote_pattern = re.compile(QUOTE_PATTERN) 
    return re.sub(quote_pattern, lambda x: replace_with[x.group(0)], word) 
4

Existe también la excelente markupsafe package.

>>> from markupsafe import Markup, escape 
>>> escape("<script>alert(document.cookie);</script>") 
Markup(u'&lt;script&gt;alert(document.cookie);&lt;/script&gt;') 

El paquete markupsafe está bien diseñado, y probablemente la forma más versátil y Pythonic ir en escapar, en mi humilde opinión, debido a que:

  1. el retorno (Markup) es una clase derivada de Unicode (es decir, isinstance(escape('str'), unicode) == True
  2. se maneja correctamente la entrada unicode
  3. funciona en Python (2.6, 2.7, 3.3, y PyPy)
  4. se respeta los métodos personalizados de objetos (es decir objetos con una propiedad __html__) y sobrecargas de plantilla (__html_format__).
Cuestiones relacionadas