cgi.escape sembra una possibile scelta. Funziona bene? C'è qualcosa che è considerato migliore?
cgi.escape sembra una possibile scelta. Funziona bene? C'è qualcosa che è considerato migliore?
Risposte:
cgi.escapeè ok. Sfugge:
< per <> per >& per &Questo è abbastanza per tutto l'HTML.
EDIT: Se hai caratteri non ascii che vuoi scappare, per l'inclusione in un altro documento codificato che utilizza una codifica diversa, come dice Craig , basta usare:
data.encode('ascii', 'xmlcharrefreplace')
Non dimenticare di decodificare dataper unicodeprimo, usando qualunque codifica sia stata codificata.
Tuttavia, nella mia esperienza, quel tipo di codifica è inutile se lavori unicodesempre dall'inizio. Basta codificare alla fine della codifica specificata nell'intestazione del documento ( utf-8per la massima compatibilità).
Esempio:
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'<a>bá</a>
Degno di nota (grazie Greg) è il quoteparametro aggiuntivo cgi.escapeprende. Se impostato su True, cgi.escapeevita anche i caratteri di virgolette doppie ( ") in modo da poter utilizzare il valore risultante in un attributo XML / HTML.
EDIT: Nota che cgi.escape è stato deprecato in Python 3.2 a favore di html.escape, che fa lo stesso tranne che per quoteimpostazione predefinita è True.
cgi.escapefunzione, è sufficiente per proteggermi da tutti gli attacchi XSS (noti)?
cgi.escape(yourunicodeobj).encode('ascii', 'xmlcharrefreplace') == '{{Measures 12 Ω"H x 17 5/8"W x 8 7/8"D. Imported.}}'- come puoi vedere, l'espressione restituisce ascii bytestring, con tutti i caratteri unicode non ascii codificati usando la tabella di riferimento dei caratteri xml.
In Python 3.2 htmlè stato introdotto un nuovo modulo, che viene utilizzato per sfuggire ai caratteri riservati dal markup HTML.
Ha una funzione 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()sfugge alle virgolette, per impostazione predefinita (al contrario, cgi.quote()non - e sfugge solo alle doppie virgolette, se detto). Quindi, devo impostare esplicitamente un parametro opzionale con cui iniettare qualcosa in un attributo html.escape(), cioè renderlo insicuro per gli attributi:t = '" onclick="alert()'; t = html.escape(t, quote=False); s = f'<a href="about.html" class="{t}">foo</a>'
escape()non è abbastanza per rendere sicuri gli attributi. In altre parole, questo non è sicuro:<a href=" {{ html.escape(untrusted_text) }} ">
href è quello di impostare una politica di sicurezza del contenuto che non lo consente.
html.escapesfugge alle virgolette singole e alle virgolette doppie.
Se desideri sfuggire all'HTML in un URL:
Questo probabilmente NON è quello che voleva l'OP (la domanda non indica chiaramente in quale contesto si debba usare l'escaping), ma l' URLlib della libreria nativa di Python ha un metodo per sfuggire alle entità HTML che devono essere incluse in un URL in modo sicuro.
Quanto segue è un esempio:
#!/usr/bin/python
from urllib import quote
x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'
C'è anche l'eccellente pacchetto markupsafe .
>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'<script>alert(document.cookie);</script>')
Il markupsafepacchetto è ben progettato, e probabilmente il modo più versatile e Pythonic per evadere, IMHO, perché:
Markup) è una classe derivata da unicode (cioèisinstance(escape('str'), unicode) == True__html__proprietà) e template overload ( __html_format__).cgi.escape dovrebbe essere buono per sfuggire all'HTML nel senso limitato di sfuggire ai tag HTML e alle entità carattere.
Ma potresti dover considerare anche i problemi di codifica: se l'HTML che vuoi citare ha caratteri non ASCII in una particolare codifica, allora dovresti anche preoccuparti di rappresentarli sensibilmente durante il preventivo. Forse potresti convertirli in entità. In caso contrario, è necessario assicurarsi che vengano eseguite le traduzioni di codifica corrette tra l'HTML "sorgente" e la pagina in cui è incorporato, per evitare di corrompere i caratteri non ASCII.
Nessuna libreria, puro Python, sfugge al testo in modo sicuro nel testo HTML:
text.replace('&', '&').replace('>', '>').replace('<', '<'
).encode('ascii', 'xmlcharrefreplace')
<verrà evaso&lt;
cgi.escape estesoQuesta versione migliora cgi.escape. Conserva anche gli spazi bianchi e le nuove righe. Restituisce una unicodestringa.
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"'
Non è il modo più semplice, ma comunque semplice. La differenza principale rispetto al modulo cgi.escape - funzionerà ancora correttamente se hai già &nel tuo testo. Come vedi dai commenti ad esso:
versione 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
versione 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)
Per il codice legacy in Python 2.7, puoi farlo tramite BeautifulSoup4 :
>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&d'