diff --git a/src/calibre/utils/xml_parse.py b/src/calibre/utils/xml_parse.py index a82d4bc773..d0228d5e3f 100644 --- a/src/calibre/utils/xml_parse.py +++ b/src/calibre/utils/xml_parse.py @@ -6,14 +6,29 @@ from __future__ import absolute_import, division, print_function, unicode_litera from lxml import etree +import threading + # resolve_entities is turned off as entities can cause # reads of local files, for example: # ]> -SAFE_XML_PARSER = etree.XMLParser(recover=True, no_network=True, resolve_entities=False) -SAFE_XML_PARSER_NO_RECOVER = etree.XMLParser(recover=False, no_network=True, resolve_entities=False) + + +class GlobalParserTLS(threading.local): + + def __call__(self, recover): + parsers = getattr(self, 'parsers', None) + if parsers is None: + self.parsers = parsers = { + True: etree.XMLParser(recover=True, no_network=True, resolve_entities=False), + False: etree.XMLParser(recover=False, no_network=True, resolve_entities=False) + } + return parsers[recover] + + +_global_tls = GlobalParserTLS() fs = etree.fromstring def safe_xml_fromstring(string_or_bytes, recover=True): - return fs(string_or_bytes, SAFE_XML_PARSER if recover else SAFE_XML_PARSER_NO_RECOVER) + return fs(string_or_bytes, _global_tls(recover))