summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Parser/ExpatParser.cpp5
-rw-r--r--Swiften/Parser/LibXMLParser.cpp7
-rw-r--r--Swiften/Parser/UnitTest/XMLParserTest.cpp35
-rw-r--r--Swiften/Parser/XMLParserClient.cpp5
-rw-r--r--Swiften/Parser/XMLParserClient.h10
5 files changed, 52 insertions, 10 deletions
diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp
index e4e66f2..a50949b 100644
--- a/Swiften/Parser/ExpatParser.cpp
+++ b/Swiften/Parser/ExpatParser.cpp
@@ -64,6 +64,10 @@ static void handleCharacterData(void* parser, const XML_Char* data, int len) {
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();
}
@@ -76,6 +80,7 @@ ExpatParser::ExpatParser(XMLParserClient* client) : XMLParser(client), p(new Pri
XML_SetCharacterDataHandler(p->parser_, handleCharacterData);
XML_SetXmlDeclHandler(p->parser_, handleXMLDeclaration);
XML_SetEntityDeclHandler(p->parser_, handleEntityDeclaration);
+ XML_SetNamespaceDeclHandler(p->parser_, handleNamespaceDeclaration, nullptr);
}
ExpatParser::~ExpatParser() {
diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp
index c9f3a07..192f44b 100644
--- a/Swiften/Parser/LibXMLParser.cpp
+++ b/Swiften/Parser/LibXMLParser.cpp
@@ -24,7 +24,7 @@ struct LibXMLParser::Private {
xmlParserCtxtPtr context_;
};
-static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) {
+static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int nbNamespaces, const xmlChar** namespaces, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) {
AttributeMap attributeValues;
if (nbDefaulted != 0) {
// Just because i don't understand what this means yet :-)
@@ -42,6 +42,11 @@ static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*
std::string(reinterpret_cast<const char*>(attributes[i+3]),
static_cast<size_t>(attributes[i+4]-attributes[i+3])));
}
+ for (auto i = 0; i < nbNamespaces * 2; i += 2) {
+ const auto prefix = namespaces[i] ? std::string(reinterpret_cast<const char*>(namespaces[i])) : "";
+ const auto uri = std::string(reinterpret_cast<const char*>(namespaces[i + 1]));
+ static_cast<XMLParser*>(parser)->getClient()->handleNamespaceDeclaration(prefix, uri);
+ }
static_cast<XMLParser*>(parser)->getClient()->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues);
}
diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp
index 9e9012b..c026b4b 100644
--- a/Swiften/Parser/UnitTest/XMLParserTest.cpp
+++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp
@@ -6,6 +6,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <unordered_map>
#include <vector>
#include <string>
@@ -61,6 +62,9 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data);
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size());
CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].namespaces.size());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].namespaces.count(""));
+ CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].namespaces[""]);
CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[2].data);
@@ -85,10 +89,13 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data);
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size());
CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].namespaces.size());
+ CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].namespaces[""]);
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[1].data);
CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].namespaces.size());
CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type);
CPPUNIT_ASSERT_EQUAL(std::string("Swift"), client_.events[2].data);
@@ -161,6 +168,8 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[0].data);
CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].ns);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].namespaces.size());
+ CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].namespaces["p"]);
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[1].data);
@@ -262,6 +271,9 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size());
CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName());
CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events[0].namespaces.size());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im"), client_.events[0].namespaces[""]);
+ CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].namespaces["f"]);
}
void testParse_BillionLaughs() {
@@ -301,6 +313,7 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[0].data);
CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].ns);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].namespaces.size());
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data);
@@ -328,14 +341,16 @@ class XMLParserTest : public CppUnit::TestFixture {
private:
class Client : public XMLParserClient {
public:
- enum Type { StartElement, EndElement, CharacterData };
+ 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,
const std::string& ns,
- const AttributeMap& attributes)
- : type(type), data(data), ns(ns), attributes(attributes) {}
+ const AttributeMap& attributes,
+ NamespaceMap namespaces = {})
+ : type(type), data(data), ns(ns), attributes(attributes), namespaces(std::move(namespaces)) {}
Event(Type type, const std::string& data, const std::string& ns = std::string())
: type(type), data(data), ns(ns) {}
@@ -343,23 +358,29 @@ class XMLParserTest : public CppUnit::TestFixture {
std::string data;
std::string ns;
AttributeMap attributes;
+ NamespaceMap namespaces;
};
Client() {}
- virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
- events.push_back(Event(StartElement, element, ns, attributes));
+ void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) override {
+ events.push_back(Event(StartElement, element, ns, attributes, std::move(namespaces_)));
}
- virtual void handleEndElement(const std::string& element, const std::string& ns) {
+ void handleEndElement(const std::string& element, const std::string& ns) override {
events.push_back(Event(EndElement, element, ns));
}
- virtual void handleCharacterData(const std::string& data) {
+ 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_;
};
diff --git a/Swiften/Parser/XMLParserClient.cpp b/Swiften/Parser/XMLParserClient.cpp
index 6dc6db6..40be4e8 100644
--- a/Swiften/Parser/XMLParserClient.cpp
+++ b/Swiften/Parser/XMLParserClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2019 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -11,5 +11,8 @@ namespace Swift {
XMLParserClient::~XMLParserClient() {
}
+void XMLParserClient::handleNamespaceDeclaration(const std::string&, const std::string&) {
+}
+
}
diff --git a/Swiften/Parser/XMLParserClient.h b/Swiften/Parser/XMLParserClient.h
index e4346f6..0682320 100644
--- a/Swiften/Parser/XMLParserClient.h
+++ b/Swiften/Parser/XMLParserClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2019 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -17,5 +17,13 @@ namespace Swift {
virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0;
virtual void handleEndElement(const std::string& element, const std::string& ns) = 0;
virtual void handleCharacterData(const std::string& data) = 0;
+
+ /**
+ * Signal that a namespace prefix has been declared
+ * This callback might be called multiple times for a single element,
+ * and will trigger before the corresponding \ref handleStartElement
+ * is called.
+ */
+ virtual void handleNamespaceDeclaration(const std::string& prefix, const std::string& uri);
};
}