// // SAXParser.cpp // // Library: XML // Package: SAX // Module: SAX // // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 // #include "Poco/SAX/SAXParser.h" #include "Poco/SAX/SAXException.h" #include "Poco/SAX/EntityResolverImpl.h" #include "Poco/SAX/InputSource.h" #include "Poco/XML/NamespaceStrategy.h" #include "Poco/NumberParser.h" #include "ParserEngine.h" #include namespace Poco { namespace XML { const XMLString SAXParser::FEATURE_PARTIAL_READS = toXMLString("http://www.appinf.com/features/enable-partial-reads"); const XMLString SAXParser::PROPERTY_BLA_MAXIMUM_AMPLIFICATION = toXMLString("http://www.appinf.com/properties/bla-maximum-amplification"); const XMLString SAXParser::PROPERTY_BLA_ACTIVATION_THRESHOLD = toXMLString("http://www.appinf.com/properties/bla-activation-threshold"); SAXParser::SAXParser(): _namespaces(true), _namespacePrefixes(false) { _engine = new ParserEngine; } SAXParser::SAXParser(const XMLString& encoding): _namespaces(true), _namespacePrefixes(false) { _engine = new ParserEngine(encoding); } SAXParser::~SAXParser() { delete _engine; } void SAXParser::setEncoding(const XMLString& encoding) { _engine->setEncoding(encoding); } const XMLString& SAXParser::getEncoding() const { return _engine->getEncoding(); } void SAXParser::addEncoding(const XMLString& name, Poco::TextEncoding* pEncoding) { _engine->addEncoding(name, pEncoding); } void SAXParser::setEntityResolver(EntityResolver* pResolver) { _engine->setEntityResolver(pResolver); } EntityResolver* SAXParser::getEntityResolver() const { return _engine->getEntityResolver(); } void SAXParser::setDTDHandler(DTDHandler* pDTDHandler) { _engine->setDTDHandler(pDTDHandler); } DTDHandler* SAXParser::getDTDHandler() const { return _engine->getDTDHandler(); } void SAXParser::setContentHandler(ContentHandler* pContentHandler) { _engine->setContentHandler(pContentHandler); } ContentHandler* SAXParser::getContentHandler() const { return _engine->getContentHandler(); } void SAXParser::setErrorHandler(ErrorHandler* pErrorHandler) { _engine->setErrorHandler(pErrorHandler); } ErrorHandler* SAXParser::getErrorHandler() const { return _engine->getErrorHandler(); } void SAXParser::setFeature(const XMLString& featureId, bool state) { if (featureId == XMLReader::FEATURE_VALIDATION || featureId == XMLReader::FEATURE_STRING_INTERNING) throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_VALIDATION)); else if (featureId == XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES) _engine->setExternalGeneralEntities(state); else if (featureId == XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES) _engine->setExternalParameterEntities(state); else if (featureId == XMLReader::FEATURE_NAMESPACES) _namespaces = state; else if (featureId == XMLReader::FEATURE_NAMESPACE_PREFIXES) _namespacePrefixes = state; else if (featureId == FEATURE_PARTIAL_READS) _engine->setEnablePartialReads(state); else throw SAXNotRecognizedException(fromXMLString(featureId)); } bool SAXParser::getFeature(const XMLString& featureId) const { if (featureId == XMLReader::FEATURE_VALIDATION || featureId == XMLReader::FEATURE_STRING_INTERNING) throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_VALIDATION)); else if (featureId == XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES) return _engine->getExternalGeneralEntities(); else if (featureId == XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES) return _engine->getExternalParameterEntities(); else if (featureId == XMLReader::FEATURE_NAMESPACES) return _namespaces; else if (featureId == XMLReader::FEATURE_NAMESPACE_PREFIXES) return _namespacePrefixes; else if (featureId == FEATURE_PARTIAL_READS) return _engine->getEnablePartialReads(); else throw SAXNotRecognizedException(fromXMLString(featureId)); } void SAXParser::setProperty(const XMLString& propertyId, const XMLString& value) { if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER || propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER) throw SAXNotSupportedException(std::string("property does not take a string value: ") + fromXMLString(propertyId)); else if (propertyId == PROPERTY_BLA_MAXIMUM_AMPLIFICATION) _engine->setBillionLaughsAttackProtectionMaximumAmplification(static_cast(Poco::NumberParser::parseFloat(value))); else if (propertyId == PROPERTY_BLA_ACTIVATION_THRESHOLD) _engine->setBillionLaughsAttackProtectionActivationThreshold(Poco::NumberParser::parseUnsigned64(value)); else throw SAXNotRecognizedException(fromXMLString(propertyId)); } void SAXParser::setProperty(const XMLString& propertyId, void* value) { if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER) _engine->setDeclHandler(reinterpret_cast(value)); else if (propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER) _engine->setLexicalHandler(reinterpret_cast(value)); else throw SAXNotRecognizedException(fromXMLString(propertyId)); } void* SAXParser::getProperty(const XMLString& propertyId) const { if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER) return _engine->getDeclHandler(); else if (propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER) return _engine->getLexicalHandler(); else throw SAXNotSupportedException(fromXMLString(propertyId)); } void SAXParser::parse(InputSource* pInputSource) { if (pInputSource->getByteStream() || pInputSource->getCharacterStream()) { setupParse(); _engine->parse(pInputSource); } else parse(pInputSource->getSystemId()); } void SAXParser::parse(const XMLString& systemId) { setupParse(); EntityResolverImpl entityResolver; InputSource* pInputSource = entityResolver.resolveEntity(0, systemId); if (pInputSource) { try { _engine->parse(pInputSource); } catch (...) { entityResolver.releaseInputSource(pInputSource); throw; } entityResolver.releaseInputSource(pInputSource); } else throw XMLException("Cannot resolve system identifier", fromXMLString(systemId)); } void SAXParser::parseString(const std::string& xml) { parseMemoryNP(xml.data(), xml.size()); } void SAXParser::parseMemoryNP(const char* xml, std::size_t size) { setupParse(); _engine->parse(xml, size); } void SAXParser::setupParse() { if (_namespaces && !_namespacePrefixes) _engine->setNamespaceStrategy(new NoNamespacePrefixesStrategy); else if (_namespaces && _namespacePrefixes) _engine->setNamespaceStrategy(new NamespacePrefixesStrategy); else _engine->setNamespaceStrategy(new NoNamespacesStrategy); } } } // namespace Poco::XML