diff options
Diffstat (limited to 'Swiften')
| -rw-r--r-- | Swiften/Parser/ExpatParser.cpp | 18 | ||||
| -rw-r--r-- | Swiften/Parser/ExpatParser.h | 2 | ||||
| -rw-r--r-- | Swiften/Parser/LibXMLParser.cpp | 30 | ||||
| -rw-r--r-- | Swiften/Parser/LibXMLParser.h | 5 | ||||
| -rw-r--r-- | Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h | 2 | ||||
| -rw-r--r-- | Swiften/Parser/PlatformXMLParserFactory.cpp | 6 | ||||
| -rw-r--r-- | Swiften/Parser/PlatformXMLParserFactory.h | 2 | ||||
| -rw-r--r-- | Swiften/Parser/UnitTest/XMLParserTest.cpp | 42 | ||||
| -rw-r--r-- | Swiften/Parser/XMLParser.cpp | 2 | ||||
| -rw-r--r-- | Swiften/Parser/XMLParser.h | 7 | ||||
| -rw-r--r-- | Swiften/Parser/XMLParserFactory.h | 2 |
11 files changed, 103 insertions, 15 deletions
diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp index a50949b..640d561 100644 --- a/Swiften/Parser/ExpatParser.cpp +++ b/Swiften/Parser/ExpatParser.cpp @@ -66,27 +66,43 @@ static void handleXMLDeclaration(void*, const XML_Char*, const XML_Char*, int) { static void handleNamespaceDeclaration(void* parser, const XML_Char* prefix, const XML_Char* uri) { static_cast<XMLParser*>(parser)->getClient()->handleNamespaceDeclaration(std::string(prefix ? prefix : ""), std::string(uri ? uri : "")); } static void handleEntityDeclaration(void* parser, const XML_Char*, int, const XML_Char*, int, const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*) { static_cast<ExpatParser*>(parser)->stopParser(); } +static void handleComment(void* parser, const XML_Char* /*data*/) { + if (!static_cast<ExpatParser*>(parser)->allowsComments()) { + static_cast<ExpatParser*>(parser)->stopParser(); + } +} + +static void handleProcessingInstruction(void* parser, const XML_Char* /*target*/, const XML_Char* /*data*/) { + static_cast<ExpatParser*>(parser)->stopParser(); +} + +static void handleDoctypeDeclaration(void* parser, const XML_Char* /*doctypeName*/, const XML_Char* /*sysid*/, const XML_Char* /*pubid*/, int /*has_internal_subset*/) { + static_cast<ExpatParser*>(parser)->stopParser(); +} -ExpatParser::ExpatParser(XMLParserClient* client) : XMLParser(client), p(new Private()) { +ExpatParser::ExpatParser(XMLParserClient* client, bool allowComments) : XMLParser(client, allowComments), p(new Private()) { p->parser_ = XML_ParserCreateNS("UTF-8", NAMESPACE_SEPARATOR); XML_SetUserData(p->parser_, this); XML_SetElementHandler(p->parser_, handleStartElement, handleEndElement); XML_SetCharacterDataHandler(p->parser_, handleCharacterData); XML_SetXmlDeclHandler(p->parser_, handleXMLDeclaration); XML_SetEntityDeclHandler(p->parser_, handleEntityDeclaration); XML_SetNamespaceDeclHandler(p->parser_, handleNamespaceDeclaration, nullptr); + XML_SetCommentHandler(p->parser_, handleComment); + XML_SetProcessingInstructionHandler(p->parser_, handleProcessingInstruction); + XML_SetDoctypeDeclHandler(p->parser_, handleDoctypeDeclaration, nullptr); } ExpatParser::~ExpatParser() { XML_ParserFree(p->parser_); } bool ExpatParser::parse(const std::string& data, bool finalData) { if (data.size() > std::numeric_limits<int>::max()) { return false; diff --git a/Swiften/Parser/ExpatParser.h b/Swiften/Parser/ExpatParser.h index 7583339..34d790d 100644 --- a/Swiften/Parser/ExpatParser.h +++ b/Swiften/Parser/ExpatParser.h @@ -10,19 +10,19 @@ #include <boost/noncopyable.hpp> #include <Swiften/Base/API.h> #include <Swiften/Parser/XMLParser.h> namespace Swift { class SWIFTEN_API ExpatParser : public XMLParser, public boost::noncopyable { public: - ExpatParser(XMLParserClient* client); + ExpatParser(XMLParserClient* client, bool allowComments = false); ~ExpatParser(); bool parse(const std::string& data, bool finalData = false); void stopParser(); private: struct Private; const std::unique_ptr<Private> p; diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp index 192f44b..4e02059 100644 --- a/Swiften/Parser/LibXMLParser.cpp +++ b/Swiften/Parser/LibXMLParser.cpp @@ -53,46 +53,68 @@ static void handleStartElement(void* parser, const xmlChar* name, const xmlChar* static void handleEndElement(void *parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns) { static_cast<XMLParser*>(parser)->getClient()->handleEndElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string())); } static void handleCharacterData(void* parser, const xmlChar* data, int len) { assert(len >= 0); static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), static_cast<size_t>(len))); } +static void handleComment(void* parser, const xmlChar* /*data*/) { + if (!static_cast<LibXMLParser*>(parser)->allowsComments()) { + static_cast<LibXMLParser*>(parser)->stopParser(); + } +} + +static void handleEntityDeclaration(void * parser, const xmlChar* /*name*/, int /*type*/, const xmlChar* /*publicId*/, const xmlChar* /*systemId*/, xmlChar* /*content*/) { + static_cast<LibXMLParser*>(parser)->stopParser(); +} + +static void handleProcessingInstruction(void* parser, const xmlChar* /*target*/, const xmlChar* /*data*/) { + static_cast<LibXMLParser*>(parser)->stopParser(); +} + +static void handleExternalSubset(void* parser, const xmlChar * /*name*/, const xmlChar * /*ExternalID*/, const xmlChar * /*SystemID*/) { + static_cast<LibXMLParser*>(parser)->stopParser(); +} + static void handleError(void*, const char* /*m*/, ... ) { /* va_list args; va_start(args, m); vfprintf(stdout, m, args); va_end(args); */ } static void handleWarning(void*, const char*, ... ) { } bool LibXMLParser::initialized = false; -LibXMLParser::LibXMLParser(XMLParserClient* client) : XMLParser(client), p(new Private()) { +LibXMLParser::LibXMLParser(XMLParserClient* client, bool allowComments) : XMLParser(client, allowComments), p(new Private()) { // Initialize libXML for multithreaded applications if (!initialized) { xmlInitParser(); initialized = true; } memset(&p->handler_, 0, sizeof(p->handler_) ); p->handler_.initialized = XML_SAX2_MAGIC; p->handler_.startElementNs = &handleStartElement; p->handler_.endElementNs = &handleEndElement; p->handler_.characters = &handleCharacterData; p->handler_.warning = &handleWarning; p->handler_.error = &handleError; + p->handler_.comment = &handleComment; + p->handler_.entityDecl = &handleEntityDeclaration; + p->handler_.processingInstruction = &handleProcessingInstruction; + p->handler_.externalSubset = &handleExternalSubset; p->context_ = xmlCreatePushParserCtxt(&p->handler_, this, nullptr, 0, nullptr); xmlCtxtUseOptions(p->context_, XML_PARSE_NOENT); assert(p->context_); } LibXMLParser::~LibXMLParser() { if (p->context_) { xmlFreeParserCtxt(p->context_); @@ -100,19 +122,25 @@ LibXMLParser::~LibXMLParser() { } bool LibXMLParser::parse(const std::string& data, bool finalData) { if (data.size() > std::numeric_limits<int>::max()) { return false; } if (xmlParseChunk(p->context_, data.c_str(), static_cast<int>(data.size()), finalData) == XML_ERR_OK) { return true; } + if (stopped_) return false; xmlError* error = xmlCtxtGetLastError(p->context_); if (error->code == XML_WAR_NS_URI || error->code == XML_WAR_NS_URI_RELATIVE) { xmlCtxtResetLastError(p->context_); p->context_->errNo = XML_ERR_OK; return true; } return false; } +void LibXMLParser::stopParser() { + stopped_ = true; + xmlStopParser(p->context_); +} + } diff --git a/Swiften/Parser/LibXMLParser.h b/Swiften/Parser/LibXMLParser.h index a863867..e21770d 100644 --- a/Swiften/Parser/LibXMLParser.h +++ b/Swiften/Parser/LibXMLParser.h @@ -13,21 +13,24 @@ #include <Swiften/Parser/XMLParser.h> namespace Swift { /** * Warning: This constructor is not thread-safe, because it depends on global state to * check whether it is initialized. */ class LibXMLParser : public XMLParser, public boost::noncopyable { public: - LibXMLParser(XMLParserClient* client); + LibXMLParser(XMLParserClient* client, bool allowComments = false); virtual ~LibXMLParser(); bool parse(const std::string& data, bool finalData = false); + void stopParser(); + private: static bool initialized; + bool stopped_ = false; struct Private; const std::unique_ptr<Private> p; }; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h index dcdbffa..8f9e0e1 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h +++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h @@ -13,19 +13,19 @@ #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Parser/XMLParser.h> #include <Swiften/Parser/XMLParserClient.h> namespace Swift { class PayloadsParserTester : public XMLParserClient { public: PayloadsParserTester() : level(0) { - xmlParser = PlatformXMLParserFactory().createXMLParser(this); + xmlParser = PlatformXMLParserFactory().createXMLParser(this, false); } bool parse(const std::string& data) { return xmlParser->parse(data); } virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { if (level == 0) { assert(!payloadParser.get()); diff --git a/Swiften/Parser/PlatformXMLParserFactory.cpp b/Swiften/Parser/PlatformXMLParserFactory.cpp index bf66734..a424aca 100644 --- a/Swiften/Parser/PlatformXMLParserFactory.cpp +++ b/Swiften/Parser/PlatformXMLParserFactory.cpp @@ -14,18 +14,18 @@ #include <Swiften/Parser/ExpatParser.h> #endif namespace Swift { PlatformXMLParserFactory::PlatformXMLParserFactory() { } -std::unique_ptr<XMLParser> PlatformXMLParserFactory::createXMLParser(XMLParserClient* client) { +std::unique_ptr<XMLParser> PlatformXMLParserFactory::createXMLParser(XMLParserClient* client, bool allowComments) { #ifdef HAVE_LIBXML - return std::make_unique<LibXMLParser>(client); + return std::make_unique<LibXMLParser>(client, allowComments); #else - return std::make_unique<ExpatParser>(client); + return std::make_unique<ExpatParser>(client, allowComments); #endif } } diff --git a/Swiften/Parser/PlatformXMLParserFactory.h b/Swiften/Parser/PlatformXMLParserFactory.h index fa3ca19..d72a513 100644 --- a/Swiften/Parser/PlatformXMLParserFactory.h +++ b/Swiften/Parser/PlatformXMLParserFactory.h @@ -8,12 +8,12 @@ #include <Swiften/Base/API.h> #include <Swiften/Parser/XMLParserFactory.h> namespace Swift { class SWIFTEN_API PlatformXMLParserFactory : public XMLParserFactory { public: PlatformXMLParserFactory(); - virtual std::unique_ptr<XMLParser> createXMLParser(XMLParserClient*); + virtual std::unique_ptr<XMLParser> createXMLParser(XMLParserClient*, bool allowComments = false); }; } diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp index c026b4b..63d30ea 100644 --- a/Swiften/Parser/UnitTest/XMLParserTest.cpp +++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp @@ -33,18 +33,22 @@ class XMLParserTest : public CppUnit::TestFixture { CPPUNIT_TEST(testParse_InErrorState); CPPUNIT_TEST(testParse_Incremental); CPPUNIT_TEST(testParse_WhitespaceInAttribute); CPPUNIT_TEST(testParse_AttributeWithoutNamespace); CPPUNIT_TEST(testParse_AttributeWithNamespace); CPPUNIT_TEST(testParse_BillionLaughs); CPPUNIT_TEST(testParse_InternalEntity); //CPPUNIT_TEST(testParse_UndefinedPrefix); //CPPUNIT_TEST(testParse_UndefinedAttributePrefix); + CPPUNIT_TEST(testParse_AllowCommentsInXML); + CPPUNIT_TEST(testParse_DisallowCommentsInXML); + CPPUNIT_TEST(testParse_Doctype); + CPPUNIT_TEST(testParse_ProcessingInstructions); CPPUNIT_TEST_SUITE_END(); public: void testParse_NestedElements() { ParserType testling(&client_); CPPUNIT_ASSERT(testling.parse( "<iq type=\"get\">" "<query xmlns='jabber:iq:version'/>" @@ -179,19 +183,19 @@ class XMLParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[2].data); CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[2].ns); CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[3].data); CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[3].ns); } void testParse_UnhandledXML() { - ParserType testling(&client_); + ParserType testling(&client_, true); CPPUNIT_ASSERT(testling.parse("<iq><!-- Testing --></iq>")); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); @@ -325,25 +329,56 @@ class XMLParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[3].data); CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[3].ns); } void testParse_UndefinedAttributePrefix() { ParserType testling(&client_); - CPPUNIT_ASSERT(testling.parse( - "<foo bar:baz='bla'/>")); + CPPUNIT_ASSERT(testling.parse("<foo bar:baz='bla'/>")); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); CPPUNIT_ASSERT_EQUAL(std::string("bar:baz"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); } + void testParse_AllowCommentsInXML() { + ParserType testling(&client_, true); + + CPPUNIT_ASSERT(testling.parse("<message><!-- Some More Comments Testing --></message>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("message"), client_.events[0].data); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("message"), client_.events[1].data); + } + + void testParse_DisallowCommentsInXML() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<message><!-- Some More Comments Testing --></message>")); + } + + void testParse_Doctype() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<!DOCTYPE greeting SYSTEM \"hello.dtd\">")); + } + + void testParse_ProcessingInstructions() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<?xml-stylesheet type=\"text/xsl\" href=\"Sample.xsl\"?>")); + } + private: class Client : public XMLParserClient { public: using NamespaceMap = std::unordered_map<std::string /* prefix */, std::string /* uri */>; enum Type { StartElement, EndElement, CharacterData, NamespaceDefined }; struct Event { Event( Type type, const std::string& data, @@ -372,18 +407,19 @@ class XMLParserTest : public CppUnit::TestFixture { } void handleCharacterData(const std::string& data) override { events.push_back(Event(CharacterData, data)); } void handleNamespaceDeclaration(const std::string& prefix, const std::string& uri) override { namespaces_[prefix] = uri; } + std::vector<Event> events; private: NamespaceMap namespaces_; } client_; }; #ifdef HAVE_EXPAT CPPUNIT_TEST_SUITE_REGISTRATION(XMLParserTest<ExpatParser>); #endif diff --git a/Swiften/Parser/XMLParser.cpp b/Swiften/Parser/XMLParser.cpp index 8e92fe4..8a0799f 100644 --- a/Swiften/Parser/XMLParser.cpp +++ b/Swiften/Parser/XMLParser.cpp @@ -2,16 +2,16 @@ * Copyright (c) 2010 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Parser/XMLParser.h> namespace Swift { -XMLParser::XMLParser(XMLParserClient* client) : client_(client) { +XMLParser::XMLParser(XMLParserClient* client, bool allowComments) : client_(client), allowComments_(allowComments){ } XMLParser::~XMLParser() { } } diff --git a/Swiften/Parser/XMLParser.h b/Swiften/Parser/XMLParser.h index ad79b2d..3b09d22 100644 --- a/Swiften/Parser/XMLParser.h +++ b/Swiften/Parser/XMLParser.h @@ -9,22 +9,27 @@ #include <string> #include <Swiften/Base/API.h> namespace Swift { class XMLParserClient; class SWIFTEN_API XMLParser { public: - XMLParser(XMLParserClient* client); + XMLParser(XMLParserClient* client, bool allowComments = false); virtual ~XMLParser(); virtual bool parse(const std::string& data, bool finalData = false) = 0; XMLParserClient* getClient() const { return client_; } + bool allowsComments() const { + return allowComments_; + } + private: XMLParserClient* client_; + const bool allowComments_ = false; }; } diff --git a/Swiften/Parser/XMLParserFactory.h b/Swiften/Parser/XMLParserFactory.h index 595512b..ae3c90e 100644 --- a/Swiften/Parser/XMLParserFactory.h +++ b/Swiften/Parser/XMLParserFactory.h @@ -12,12 +12,12 @@ namespace Swift { class XMLParser; class XMLParserClient; class SWIFTEN_API XMLParserFactory { public: virtual ~XMLParserFactory(); - virtual std::unique_ptr<XMLParser> createXMLParser(XMLParserClient*) = 0; + virtual std::unique_ptr<XMLParser> createXMLParser(XMLParserClient*, bool allowComments = false) = 0; }; } |
Swift