Skip to content

Commit 75eb48b

Browse files
author
Matthijs Mekking
committed
patch to html5lib to strip tags
- Legacy-Id: 2459
1 parent f9c30a1 commit 75eb48b

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

matthijs/html5lib/sanitizer.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ class HTMLSanitizerMixin(object):
119119
'mailto', 'news', 'gopher', 'nntp', 'telnet', 'webcal',
120120
'xmpp', 'callto', 'feed', 'urn', 'aim', 'rsync', 'tag',
121121
'ssh', 'sftp', 'rtsp', 'afs' ]
122+
123+
124+
# block elements whose contents will be stripped completely if we we are
125+
# stripping tokens during sanitization.
126+
unacceptable_block_elements = [ 'script', 'style' ]
122127

123128
# subclasses may define their own versions of these constants
124129
allowed_elements = acceptable_elements + mathml_elements + svg_elements
@@ -139,7 +144,7 @@ class HTMLSanitizerMixin(object):
139144
# => <script> do_nasty_stuff() </script>
140145
# sanitize_html('<a href="javascript: sucker();">Click here for $100</a>')
141146
# => <a>Click here for $100</a>
142-
def sanitize_token(self, token):
147+
def sanitize_token(self, token, strip_tokens=False):
143148
if token["type"] in (tokenTypes["StartTag"], tokenTypes["EndTag"],
144149
tokenTypes["EmptyTag"]):
145150
if token["name"] in self.allowed_elements:
@@ -172,6 +177,8 @@ def sanitize_token(self, token):
172177
token["data"] = [[name,val] for name,val in attrs.items()]
173178
return token
174179
else:
180+
if strip_tokens:
181+
return None
175182
if token["type"] == tokenTypes["EndTag"]:
176183
token["data"] = "</%s>" % token["name"]
177184
elif token["data"]:
@@ -216,15 +223,32 @@ def sanitize_css(self, style):
216223
return ' '.join(clean)
217224

218225
class HTMLSanitizer(HTMLTokenizer, HTMLSanitizerMixin):
226+
# strip tokens instead of escaping them
227+
strip_tokens = False
228+
219229
def __init__(self, stream, encoding=None, parseMeta=True, useChardet=True,
220230
lowercaseElementName=False, lowercaseAttrName=False):
221231
#Change case matching defaults as we only output lowercase html anyway
222232
#This solution doesn't seem ideal...
223233
HTMLTokenizer.__init__(self, stream, encoding, parseMeta, useChardet,
224234
lowercaseElementName, lowercaseAttrName)
235+
# flag to indicate if stripping is going on or not
236+
self.stripping = 0
225237

226238
def __iter__(self):
227239
for token in HTMLTokenizer.__iter__(self):
228-
token = self.sanitize_token(token)
229-
if token:
230-
yield token
240+
# if its a start tag and is a risky block element (e.g. script), we
241+
# indicate that we are in striping mode. Its a counter which allows us
242+
# to handle nested risky block elements
243+
if self.strip_tokens and token["type"] in ["StartTag", "EndTag"] \
244+
and token["name"].lower() in HTMLSanitizerMixin.unacceptable_block_elements:
245+
if token["type"] == "StartTag":
246+
self.stripping += 1
247+
elif token["type"] == "EndTag":
248+
self.stripping -= 1
249+
250+
# Only yield tokens if we are not in stripping mode
251+
if self.stripping < 1:
252+
token = self.sanitize_token(token, self.strip_tokens)
253+
if token:
254+
yield token

0 commit comments

Comments
 (0)