1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2013 IBM Corp.
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6
# not use this file except in compliance with the License. You may obtain
7
# a copy of the License at
9
# http://www.apache.org/licenses/LICENSE-2.0
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
# License for the specific language governing permissions and limitations
17
from xml.dom import minidom
18
from xml.parsers import expat
20
from xml.sax import expatreader
23
class ProtectedExpatParser(expatreader.ExpatParser):
24
"""An expat parser which disables DTD's and entities by default."""
26
def __init__(self, forbid_dtd=True, forbid_entities=True,
28
# Python 2.x old style class
29
expatreader.ExpatParser.__init__(self, *args, **kwargs)
30
self.forbid_dtd = forbid_dtd
31
self.forbid_entities = forbid_entities
33
def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
34
raise ValueError("Inline DTD forbidden")
36
def entity_decl(self, entityName, is_parameter_entity, value, base,
37
systemId, publicId, notationName):
38
raise ValueError("<!ENTITY> entity declaration forbidden")
40
def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):
42
raise ValueError("<!ENTITY> unparsed entity forbidden")
44
def external_entity_ref(self, context, base, systemId, publicId):
45
raise ValueError("<!ENTITY> external entity forbidden")
47
def notation_decl(self, name, base, sysid, pubid):
48
raise ValueError("<!ENTITY> notation forbidden")
51
expatreader.ExpatParser.reset(self)
53
self._parser.StartDoctypeDeclHandler = self.start_doctype_decl
54
self._parser.EndDoctypeDeclHandler = None
55
if self.forbid_entities:
56
self._parser.EntityDeclHandler = self.entity_decl
57
self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl
58
self._parser.ExternalEntityRefHandler = self.external_entity_ref
59
self._parser.NotationDeclHandler = self.notation_decl
61
self._parser.SkippedEntityHandler = None
62
except AttributeError:
63
# some pyexpat versions do not support SkippedEntity
67
def safe_minidom_parse_string(xml_string):
68
"""Parse an XML string using minidom safely.
72
return minidom.parseString(xml_string, parser=ProtectedExpatParser())
73
except sax.SAXParseException:
74
raise expat.ExpatError()