cgi.escape semble être un choix possible. Ça marche bien? Y a-t-il quelque chose qui est considéré comme meilleur?
cgi.escape semble être un choix possible. Ça marche bien? Y a-t-il quelque chose qui est considéré comme meilleur?
Réponses:
cgi.escapec'est bien. Il s'échappe:
< à <> à >& à &Cela suffit pour tout HTML.
EDIT: Si vous avez des caractères non-ascii que vous souhaitez également échapper, pour l'inclusion dans un autre document encodé qui utilise un encodage différent, comme le dit Craig , utilisez simplement:
data.encode('ascii', 'xmlcharrefreplace')
N'oubliez pas de décoder dataen unicodepremier, en utilisant le codage pour lequel il a été encodé.
Cependant, d'après mon expérience, ce type d'encodage est inutile si vous travaillez avec unicodetout le temps depuis le début. Encodez simplement à la fin le codage spécifié dans l'en-tête du document ( utf-8pour une compatibilité maximale).
Exemple:
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'<a>bá</a>
Il convient également de noter (merci Greg) le quoteparamètre supplémentaire cgi.escapeprend. Lorsqu'il est défini sur True, cgi.escapeéchappe également les caractères entre guillemets doubles ( ") afin que vous puissiez utiliser la valeur résultante dans un attribut XML / HTML.
EDIT: Notez que cgi.escape est obsolète dans Python 3.2 au profit de html.escape, qui fait la même chose sauf que la valeur par quotedéfaut est True.
cgi.escapefonction, est-ce suffisant pour me protéger contre tous les attacs XSS (connus)?
cgi.escape(yourunicodeobj).encode('ascii', 'xmlcharrefreplace') == '{{Measures 12 Ω"H x 17 5/8"W x 8 7/8"D. Imported.}}'- comme vous pouvez le voir, l'expression renvoie une chaîne d'octets ascii, avec tous les caractères unicode non-ascii codés à l'aide de la table de référence des caractères xml.
Dans Python 3.2, un nouveau htmlmodule a été introduit, qui est utilisé pour échapper les caractères réservés du balisage HTML.
Il a une fonction escape():
>>> import html
>>> html.escape('x > 2 && x < 7 single quote: \' double quote: "')
'x > 2 && x < 7 single quote: ' double quote: "'
quote=True?
html.escape()guillemets d'échappement, par défaut (en revanche, cgi.quote()ne le font pas - et n'échappent que les guillemets doubles, si cela est dit). Ainsi, je dois définir explicitement un paramètre optionnel avec lequel injecter quelque chose dans un attribut html.escape(), c'est-à-dire pour le rendre non sécurisé pour les attributs:t = '" onclick="alert()'; t = html.escape(t, quote=False); s = f'<a href="about.html" class="{t}">foo</a>'
escape()n'est pas suffisant pour sécuriser les attributs. En d'autres termes, ce n'est pas sûr:<a href=" {{ html.escape(untrusted_text) }} ">
href définition d'une politique de sécurité du contenu qui l'interdit.
html.escapeguillemets simples et doubles.
Si vous souhaitez échapper du HTML dans une URL:
Ce n'est probablement PAS ce que l'OP voulait (la question n'indique pas clairement dans quel contexte l'échappement est censé être utilisé), mais la bibliothèque native de Python urllib a une méthode pour échapper aux entités HTML qui doivent être incluses dans une URL en toute sécurité.
Ce qui suit est un exemple:
#!/usr/bin/python
from urllib import quote
x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'
Il existe également l'excellent package markupsafe .
>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'<script>alert(document.cookie);</script>')
Le markupsafepaquet est bien conçu, et probablement le moyen le plus polyvalent et le plus pythonique de s'échapper, à mon humble avis, car:
Markup) est une classe dérivée de unicode (ieisinstance(escape('str'), unicode) == True__html__propriété) et les surcharges de gabarit ( __html_format__).cgi.escape devrait être bon pour échapper au HTML dans le sens limité d'échapper aux balises HTML et aux entités de caractères.
Mais vous devrez peut-être également prendre en compte les problèmes d'encodage: si le code HTML que vous souhaitez citer contient des caractères non ASCII dans un encodage particulier, vous devez également veiller à les représenter de manière raisonnable lorsque vous les citez. Vous pourriez peut-être les convertir en entités. Sinon, vous devez vous assurer que les traductions de codage correctes sont effectuées entre le HTML «source» et la page dans laquelle il est intégré, pour éviter de corrompre les caractères non ASCII.
Aucune bibliothèque, pur python, échappe en toute sécurité le texte en texte html:
text.replace('&', '&').replace('>', '>').replace('<', '<'
).encode('ascii', 'xmlcharrefreplace')
<sera échappé à&lt;
cgi.escape élargiCette version s'améliore cgi.escape. Il préserve également les espaces et les nouvelles lignes. Renvoie une unicodechaîne.
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' ').\
replace(u' ', u' ')
>>> escape_html('<foo>\nfoo\t"bar"')
u'<foo><br />foo "bar"'
Pas le moyen le plus simple, mais toujours simple. La principale différence avec le module cgi.escape - il fonctionnera toujours correctement si vous en avez déjà &dans votre texte. Comme vous le voyez dans les commentaires:
version cgi.escape
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("&", "&") # Must be done first!
s = s.replace("<", "<")
s = s.replace(">", ">")
if quote:
s = s.replace('"', """)
return s
version regex
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 = {
'<': '>',
'>': '<',
'&': '&',
'"': '"', # should be escaped in attributes
"'": ''' # should be escaped in attributes
}
quote_pattern = re.compile(QUOTE_PATTERN)
return re.sub(quote_pattern, lambda x: replace_with[x.group(0)], word)
Pour le code hérité en Python 2.7, vous pouvez le faire via BeautifulSoup4 :
>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&d'