You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.7 KiB

4 years ago
  1. # defusedxml
  2. #
  3. # Copyright (c) 2013 by Christian Heimes <christian@python.org>
  4. # Licensed to PSF under a Contributor Agreement.
  5. # See http://www.python.org/psf/license for licensing details.
  6. """Defused xml.etree.ElementTree facade
  7. """
  8. from __future__ import print_function, absolute_import
  9. import sys
  10. from xml.etree.ElementTree import TreeBuilder as _TreeBuilder
  11. from xml.etree.ElementTree import parse as _parse
  12. from xml.etree.ElementTree import tostring
  13. from .common import PY3
  14. if PY3:
  15. import importlib
  16. else:
  17. from xml.etree.ElementTree import XMLParser as _XMLParser
  18. from xml.etree.ElementTree import iterparse as _iterparse
  19. from xml.etree.ElementTree import ParseError
  20. from .common import (DTDForbidden, EntitiesForbidden,
  21. ExternalReferenceForbidden, _generate_etree_functions)
  22. __origin__ = "xml.etree.ElementTree"
  23. def _get_py3_cls():
  24. """Python 3.3 hides the pure Python code but defusedxml requires it.
  25. The code is based on test.support.import_fresh_module().
  26. """
  27. pymodname = "xml.etree.ElementTree"
  28. cmodname = "_elementtree"
  29. pymod = sys.modules.pop(pymodname, None)
  30. cmod = sys.modules.pop(cmodname, None)
  31. sys.modules[cmodname] = None
  32. pure_pymod = importlib.import_module(pymodname)
  33. if cmod is not None:
  34. sys.modules[cmodname] = cmod
  35. else:
  36. sys.modules.pop(cmodname)
  37. sys.modules[pymodname] = pymod
  38. _XMLParser = pure_pymod.XMLParser
  39. _iterparse = pure_pymod.iterparse
  40. ParseError = pure_pymod.ParseError
  41. return _XMLParser, _iterparse, ParseError
  42. if PY3:
  43. _XMLParser, _iterparse, ParseError = _get_py3_cls()
  44. class DefusedXMLParser(_XMLParser):
  45. def __init__(self, html=0, target=None, encoding=None,
  46. forbid_dtd=False, forbid_entities=True,
  47. forbid_external=True):
  48. # Python 2.x old style class
  49. _XMLParser.__init__(self, html, target, encoding)
  50. self.forbid_dtd = forbid_dtd
  51. self.forbid_entities = forbid_entities
  52. self.forbid_external = forbid_external
  53. if PY3:
  54. parser = self.parser
  55. else:
  56. parser = self._parser
  57. if self.forbid_dtd:
  58. parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl
  59. if self.forbid_entities:
  60. parser.EntityDeclHandler = self.defused_entity_decl
  61. parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl
  62. if self.forbid_external:
  63. parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler
  64. def defused_start_doctype_decl(self, name, sysid, pubid,
  65. has_internal_subset):
  66. raise DTDForbidden(name, sysid, pubid)
  67. def defused_entity_decl(self, name, is_parameter_entity, value, base,
  68. sysid, pubid, notation_name):
  69. raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
  70. def defused_unparsed_entity_decl(self, name, base, sysid, pubid,
  71. notation_name):
  72. # expat 1.2
  73. raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
  74. def defused_external_entity_ref_handler(self, context, base, sysid,
  75. pubid):
  76. raise ExternalReferenceForbidden(context, base, sysid, pubid)
  77. # aliases
  78. XMLTreeBuilder = XMLParse = DefusedXMLParser
  79. parse, iterparse, fromstring = _generate_etree_functions(DefusedXMLParser,
  80. _TreeBuilder, _parse,
  81. _iterparse)
  82. XML = fromstring
  83. __all__ = ['XML', 'XMLParse', 'XMLTreeBuilder', 'fromstring', 'iterparse',
  84. 'parse', 'tostring']