8
8
from django.utils.xmlutils import SimplerXMLGenerator
9
9
from django.utils.encoding import smart_unicode
10
10
from xml.dom import pulldom
11
+
from xml.sax import handler
12
+
from xml.sax.expatreader import ExpatParser as _ExpatParser
11
13
12
14
class Serializer(base.Serializer):
13
15
"""
@@ -154,9 +156,13 @@ class Deserializer(base.Deserializer):
154
156
155
157
def __init__(self, stream_or_string, **options):
156
158
super(Deserializer, self).__init__(stream_or_string, **options)
157
-
self.event_stream = pulldom.parse(self.stream)
159
+
self.event_stream = pulldom.parse(self.stream, self._make_parser())
158
160
self.db = options.pop('using', DEFAULT_DB_ALIAS)
159
161
162
+
def _make_parser(self):
163
+
"""Create a hardened XML parser (no custom/external entities)."""
164
+
return DefusedExpatParser()
165
+
160
166
def next(self):
161
167
for event, node in self.event_stream:
162
168
if event == "START_ELEMENT" and node.nodeName == "object":
@@ -295,3 +301,89 @@ def getInnerText(node):
295
301
else:
296
302
pass
297
303
return u"".join(inner_text)
304
+
305
+
306
+
# Below code based on Christian Heimes' defusedxml
307
+
308
+
309
+
class DefusedExpatParser(_ExpatParser):
310
+
"""
311
+
An expat parser hardened against XML bomb attacks.
312
+
313
+
Forbids DTDs, external entity references
314
+
315
+
"""
316
+
def __init__(self, *args, **kwargs):
317
+
_ExpatParser.__init__(self, *args, **kwargs)
318
+
self.setFeature(handler.feature_external_ges, False)
319
+
self.setFeature(handler.feature_external_pes, False)
320
+
321
+
def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
322
+
raise DTDForbidden(name, sysid, pubid)
323
+
324
+
def entity_decl(self, name, is_parameter_entity, value, base,
325
+
sysid, pubid, notation_name):
326
+
raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
327
+
328
+
def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):
329
+
# expat 1.2
330
+
raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
331
+
332
+
def external_entity_ref_handler(self, context, base, sysid, pubid):
333
+
raise ExternalReferenceForbidden(context, base, sysid, pubid)
334
+
335
+
def reset(self):
336
+
_ExpatParser.reset(self)
337
+
parser = self._parser
338
+
parser.StartDoctypeDeclHandler = self.start_doctype_decl
339
+
parser.EntityDeclHandler = self.entity_decl
340
+
parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl
341
+
parser.ExternalEntityRefHandler = self.external_entity_ref_handler
342
+
343
+
344
+
class DefusedXmlException(ValueError):
345
+
"""Base exception."""
346
+
def __repr__(self):
347
+
return str(self)
348
+
349
+
350
+
class DTDForbidden(DefusedXmlException):
351
+
"""Document type definition is forbidden."""
352
+
def __init__(self, name, sysid, pubid):
353
+
self.name = name
354
+
self.sysid = sysid
355
+
self.pubid = pubid
356
+
357
+
def __str__(self):
358
+
tpl = "DTDForbidden(name='{}', system_id={!r}, public_id={!r})"
359
+
return tpl.format(self.name, self.sysid, self.pubid)
360
+
361
+
362
+
class EntitiesForbidden(DefusedXmlException):
363
+
"""Entity definition is forbidden."""
364
+
def __init__(self, name, value, base, sysid, pubid, notation_name):
365
+
super(EntitiesForbidden, self).__init__()
366
+
self.name = name
367
+
self.value = value
368
+
self.base = base
369
+
self.sysid = sysid
370
+
self.pubid = pubid
371
+
self.notation_name = notation_name
372
+
373
+
def __str__(self):
374
+
tpl = "EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})"
375
+
return tpl.format(self.name, self.sysid, self.pubid)
376
+
377
+
378
+
class ExternalReferenceForbidden(DefusedXmlException):
379
+
"""Resolving an external reference is forbidden."""
380
+
def __init__(self, context, base, sysid, pubid):
381
+
super(ExternalReferenceForbidden, self).__init__()
382
+
self.context = context
383
+
self.base = base
384
+
self.sysid = sysid
385
+
self.pubid = pubid
386
+
387
+
def __str__(self):
388
+
tpl = "ExternalReferenceForbidden(system_id='{}', public_id={})"
389
+
return tpl.format(self.sysid, self.pubid)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4