514
518
return self.done.wait()
521
class ProtectedExpatParser(expatreader.ExpatParser):
522
"""An expat parser which disables DTD's and entities by default."""
524
def __init__(self, forbid_dtd=True, forbid_entities=True,
526
# Python 2.x old style class
527
expatreader.ExpatParser.__init__(self, *args, **kwargs)
528
self.forbid_dtd = forbid_dtd
529
self.forbid_entities = forbid_entities
531
def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
532
raise ValueError("Inline DTD forbidden")
534
def entity_decl(self, entityName, is_parameter_entity, value, base,
535
systemId, publicId, notationName):
536
raise ValueError("<!ENTITY> forbidden")
538
def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):
540
raise ValueError("<!ENTITY> forbidden")
543
expatreader.ExpatParser.reset(self)
545
self._parser.StartDoctypeDeclHandler = self.start_doctype_decl
546
if self.forbid_entities:
547
self._parser.EntityDeclHandler = self.entity_decl
548
self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl
551
def safe_minidom_parse_string(xml_string):
552
"""Parse an XML string using minidom safely.
556
return minidom.parseString(xml_string, parser=ProtectedExpatParser())
557
except sax.SAXParseException as se:
558
raise expat.ExpatError()
517
561
def xhtml_escape(value):
518
562
"""Escapes a string so it is valid within XML or XHTML.