2009-06-30 22 views

Odpowiedz

159

cgi.escape jest w porządku. Ucieka:

  • < do &lt;
  • > do &gt;
  • & do &amp;

to wystarczy dla wszystkich HTML.

EDIT: Jeśli masz non-ASCII znaki również chcesz uciec, do włączenia do innego zakodowanego dokumentu, który używa innego kodowania, jak Craig mówi, wystarczy użyć:

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

Nie zapomnij najpierw rozkodować data na unicode, używając dowolnego kodowania, które zostało zakodowane.

Jednak z mojego doświadczenia wynika, że ​​takie kodowanie jest bezużyteczne, jeśli po prostu pracujesz z unicode przez cały czas od rozpoczęcia. Po prostu zakoduj kodowanie określone w nagłówku dokumentu (utf-8, aby uzyskać maksymalną zgodność).

Przykład:

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

Warto również zauważyć (dzięki Greg) jest dodatkowy parametr quotecgi.escape trwa. Dzięki niemu ustawiona na True, cgi.escape powoduje również uniknięcie podwójnego cudzysłowu ("), aby można było użyć wartości wynikowej w atrybucie XML/HTML.

EDIT: Zauważ, że cgi.escape została zaniechana w Pythonie 3.2 na rzecz html.escape, który robi to samo z tym że quote domyślnych true.

+7

Dodatkowy parametr boolowski dla cgi.escape powinien również być brany pod uwagę przy wycofywaniu cudzysłowu, gdy tekst jest używany w wartościach atrybutów HTML. –

+0

Tylko dla pewności: Jeśli uruchomię wszystkie niezaufane dane przez 'cgi.funkcja ucieczki, wystarcza, aby chronić przed wszystkimi (znanymi) attacami XSS? –

+0

@ Tomas Sedovic: Zależy od tego, gdzie umieścisz tekst po uruchomieniu cgi.escape w nim. Jeśli jest umieszczony w głównym kontekście HTML, to tak, jesteś całkowicie bezpieczny. – nosklo

8

cgi.escape powinno być dobre, aby uciec z HTML w ograniczonym sensie ucieczki z tagów HTML i encji znakowych.

Ale może być również konieczne rozważenie problemów z kodowaniem: jeśli kod HTML, który chcesz zacytować, zawiera znaki spoza zestawu ASCII w określonym kodowaniu, musisz również zadbać o to, aby były one rozsądnie reprezentowane podczas cytowania. Być może mógłbyś przekonwertować je na podmioty. W przeciwnym razie należy upewnić się, że wykonywane są odpowiednie tłumaczenia kodowania między "źródłowym" kodem HTML i stroną, na której jest osadzony, aby uniknąć uszkodzenia znaków spoza ASCII.

65

W Pythonie 3.2 wprowadzono nowy moduł html, który służy do usuwania znaków zastrzeżonych ze znaczników HTML.

Posiada jedną funkcję escape():

>>> import html 
>>> html.escape('x > 2 && x < 7') 
'x &gt; 2 &amp;&amp; x &lt; 7' 
+4

OSTRZEŻENIE: Nie używaj tego dla wartości atrybutów, wygrał ' t uciekaj od rzeczy takich jak (ani cgi.escape). –

6

Jeśli chcesz uciec HTML w adresie URL:

to prawdopodobnie nie jest to, co chciał OP (kwestia nie należy wyraźnie wskazać w z którego kontekstu ma korzystać escaping), ale natywna biblioteka Pythona urllib ma metodę unikania encji HTML, które muszą być bezpiecznie zawarte w adresie URL.

Poniższy przykład:

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

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

Find docs here

+5

To jest niewłaściwy rodzaj ucieczki; szukamy [ucieczki HTML] (http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references), w przeciwieństwie do [kodowania URL] (http://en.wikipedia.org/wiki/URL_Encoding). – Chaosphere2112

+2

Mimo to - właśnie tego szukałem ;-) – Brad

2

cgi.escape przedłużony

Wersja ta poprawia cgi.escape. Zachowuje również białe spacje i znaki nowej linii. Zwraca ciąg znaków 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;') 

np

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

Nie najprostszy sposób, ale nadal proste. Główna różnica od modułu cgi.escape - nadal będzie działać poprawnie, jeśli masz już w swoim tekście &amp;. Jak widać z komentarzy do niego:

cgi.escape wersja

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 

regex wersja

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

Istnieje również doskonałe markupsafe package.

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

Pakiet markupsafe jest dobrze zaprojektowane, i prawdopodobnie najbardziej wszechstronny i pythonic droga o ucieczce, IMHO, ponieważ:

  1. powrót (Markup) to klasa pochodzi z unicode (czyli isinstance(escape('str'), unicode) == True
  2. to poprawnie obsługuje wejście unicode
  3. działa w Pythonie (2.6, 2.7, 3.3 i pypy)
  4. to respektuje niestandardowe metody obiektów (tj. obiekty o właściwościach __html__) i przeciążenia szablonów (__html_format__).
Powiązane problemy