summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdwin Mons <edwin.mons@isode.com>2019-07-22 08:54:55 (GMT)
committerEdwin Mons <edwin.mons@isode.com>2019-07-22 10:13:33 (GMT)
commitf6fb85ba98fdd6601c4b8323c51c8367ccc4b52e (patch)
tree16f37c7ad860a527aac7e29e4b9d7e61bf1b635f
parentf4b6bfbf4c1573e9914185e2ef170f47838ea11a (diff)
downloadswift-f6fb85ba98fdd6601c4b8323c51c8367ccc4b52e.zip
swift-f6fb85ba98fdd6601c4b8323c51c8367ccc4b52e.tar.bz2
Signal namespace declarations to ParserClients
Prior to calling handleStartElement, the ParserClient handleNamespaceDeclaration will fire for each namespace declared on the element. Test-Information: Unit tests pass on Debian 9 for both expat and libxml2 Change-Id: Ic42e83aee83edfbb2aa5c971997808eb6e133223
-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) {
64static void handleXMLDeclaration(void*, const XML_Char*, const XML_Char*, int) { 64static void handleXMLDeclaration(void*, const XML_Char*, const XML_Char*, int) {
65} 65}
66 66
67static void handleNamespaceDeclaration(void* parser, const XML_Char* prefix, const XML_Char* uri) {
68 static_cast<XMLParser*>(parser)->getClient()->handleNamespaceDeclaration(std::string(prefix ? prefix : ""), std::string(uri ? uri : ""));
69}
70
67static void handleEntityDeclaration(void* parser, const XML_Char*, int, const XML_Char*, int, const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*) { 71static void handleEntityDeclaration(void* parser, const XML_Char*, int, const XML_Char*, int, const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*) {
68 static_cast<ExpatParser*>(parser)->stopParser(); 72 static_cast<ExpatParser*>(parser)->stopParser();
69} 73}
@@ -76,6 +80,7 @@ ExpatParser::ExpatParser(XMLParserClient* client) : XMLParser(client), p(new Pri
76 XML_SetCharacterDataHandler(p->parser_, handleCharacterData); 80 XML_SetCharacterDataHandler(p->parser_, handleCharacterData);
77 XML_SetXmlDeclHandler(p->parser_, handleXMLDeclaration); 81 XML_SetXmlDeclHandler(p->parser_, handleXMLDeclaration);
78 XML_SetEntityDeclHandler(p->parser_, handleEntityDeclaration); 82 XML_SetEntityDeclHandler(p->parser_, handleEntityDeclaration);
83 XML_SetNamespaceDeclHandler(p->parser_, handleNamespaceDeclaration, nullptr);
79} 84}
80 85
81ExpatParser::~ExpatParser() { 86ExpatParser::~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 {
24 xmlParserCtxtPtr context_; 24 xmlParserCtxtPtr context_;
25}; 25};
26 26
27static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) { 27static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int nbNamespaces, const xmlChar** namespaces, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) {
28 AttributeMap attributeValues; 28 AttributeMap attributeValues;
29 if (nbDefaulted != 0) { 29 if (nbDefaulted != 0) {
30 // Just because i don't understand what this means yet :-) 30 // Just because i don't understand what this means yet :-)
@@ -42,6 +42,11 @@ static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*
42 std::string(reinterpret_cast<const char*>(attributes[i+3]), 42 std::string(reinterpret_cast<const char*>(attributes[i+3]),
43 static_cast<size_t>(attributes[i+4]-attributes[i+3]))); 43 static_cast<size_t>(attributes[i+4]-attributes[i+3])));
44 } 44 }
45 for (auto i = 0; i < nbNamespaces * 2; i += 2) {
46 const auto prefix = namespaces[i] ? std::string(reinterpret_cast<const char*>(namespaces[i])) : "";
47 const auto uri = std::string(reinterpret_cast<const char*>(namespaces[i + 1]));
48 static_cast<XMLParser*>(parser)->getClient()->handleNamespaceDeclaration(prefix, uri);
49 }
45 static_cast<XMLParser*>(parser)->getClient()->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues); 50 static_cast<XMLParser*>(parser)->getClient()->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues);
46} 51}
47 52
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 @@
6 6
7#include <cppunit/extensions/HelperMacros.h> 7#include <cppunit/extensions/HelperMacros.h>
8#include <cppunit/extensions/TestFactoryRegistry.h> 8#include <cppunit/extensions/TestFactoryRegistry.h>
9#include <unordered_map>
9#include <vector> 10#include <vector>
10 11
11#include <string> 12#include <string>
@@ -61,6 +62,9 @@ class XMLParserTest : public CppUnit::TestFixture {
61 CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data); 62 CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data);
62 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size()); 63 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size());
63 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns); 64 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns);
65 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].namespaces.size());
66 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].namespaces.count(""));
67 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].namespaces[""]);
64 68
65 CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); 69 CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
66 CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[2].data); 70 CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[2].data);
@@ -85,10 +89,13 @@ class XMLParserTest : public CppUnit::TestFixture {
85 CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data); 89 CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data);
86 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size()); 90 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size());
87 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns); 91 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns);
92 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].namespaces.size());
93 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].namespaces[""]);
88 94
89 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); 95 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
90 CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[1].data); 96 CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[1].data);
91 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns); 97 CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns);
98 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].namespaces.size());
92 99
93 CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type); 100 CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type);
94 CPPUNIT_ASSERT_EQUAL(std::string("Swift"), client_.events[2].data); 101 CPPUNIT_ASSERT_EQUAL(std::string("Swift"), client_.events[2].data);
@@ -161,6 +168,8 @@ class XMLParserTest : public CppUnit::TestFixture {
161 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); 168 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
162 CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[0].data); 169 CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[0].data);
163 CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].ns); 170 CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].ns);
171 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].namespaces.size());
172 CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].namespaces["p"]);
164 173
165 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); 174 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
166 CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[1].data); 175 CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[1].data);
@@ -262,6 +271,9 @@ class XMLParserTest : public CppUnit::TestFixture {
262 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); 271 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size());
263 CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); 272 CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName());
264 CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); 273 CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace());
274 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events[0].namespaces.size());
275 CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im"), client_.events[0].namespaces[""]);
276 CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].namespaces["f"]);
265 } 277 }
266 278
267 void testParse_BillionLaughs() { 279 void testParse_BillionLaughs() {
@@ -301,6 +313,7 @@ class XMLParserTest : public CppUnit::TestFixture {
301 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); 313 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
302 CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[0].data); 314 CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[0].data);
303 CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].ns); 315 CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].ns);
316 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].namespaces.size());
304 317
305 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); 318 CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
306 CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data); 319 CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data);
@@ -328,14 +341,16 @@ class XMLParserTest : public CppUnit::TestFixture {
328 private: 341 private:
329 class Client : public XMLParserClient { 342 class Client : public XMLParserClient {
330 public: 343 public:
331 enum Type { StartElement, EndElement, CharacterData }; 344 using NamespaceMap = std::unordered_map<std::string /* prefix */, std::string /* uri */>;
345 enum Type { StartElement, EndElement, CharacterData, NamespaceDefined };
332 struct Event { 346 struct Event {
333 Event( 347 Event(
334 Type type, 348 Type type,
335 const std::string& data, 349 const std::string& data,
336 const std::string& ns, 350 const std::string& ns,
337 const AttributeMap& attributes) 351 const AttributeMap& attributes,
338 : type(type), data(data), ns(ns), attributes(attributes) {} 352 NamespaceMap namespaces = {})
353 : type(type), data(data), ns(ns), attributes(attributes), namespaces(std::move(namespaces)) {}
339 Event(Type type, const std::string& data, const std::string& ns = std::string()) 354 Event(Type type, const std::string& data, const std::string& ns = std::string())
340 : type(type), data(data), ns(ns) {} 355 : type(type), data(data), ns(ns) {}
341 356
@@ -343,23 +358,29 @@ class XMLParserTest : public CppUnit::TestFixture {
343 std::string data; 358 std::string data;
344 std::string ns; 359 std::string ns;
345 AttributeMap attributes; 360 AttributeMap attributes;
361 NamespaceMap namespaces;
346 }; 362 };
347 363
348 Client() {} 364 Client() {}
349 365
350 virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { 366 void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) override {
351 events.push_back(Event(StartElement, element, ns, attributes)); 367 events.push_back(Event(StartElement, element, ns, attributes, std::move(namespaces_)));
352 } 368 }
353 369
354 virtual void handleEndElement(const std::string& element, const std::string& ns) { 370 void handleEndElement(const std::string& element, const std::string& ns) override {
355 events.push_back(Event(EndElement, element, ns)); 371 events.push_back(Event(EndElement, element, ns));
356 } 372 }
357 373
358 virtual void handleCharacterData(const std::string& data) { 374 void handleCharacterData(const std::string& data) override {
359 events.push_back(Event(CharacterData, data)); 375 events.push_back(Event(CharacterData, data));
360 } 376 }
361 377
378 void handleNamespaceDeclaration(const std::string& prefix, const std::string& uri) override {
379 namespaces_[prefix] = uri;
380 }
362 std::vector<Event> events; 381 std::vector<Event> events;
382 private:
383 NamespaceMap namespaces_;
363 } client_; 384 } client_;
364}; 385};
365 386
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 @@
1/* 1/*
2 * Copyright (c) 2010 Isode Limited. 2 * Copyright (c) 2010-2019 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
@@ -11,5 +11,8 @@ namespace Swift {
11XMLParserClient::~XMLParserClient() { 11XMLParserClient::~XMLParserClient() {
12} 12}
13 13
14void XMLParserClient::handleNamespaceDeclaration(const std::string&, const std::string&) {
15}
16
14} 17}
15 18
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 @@
1/* 1/*
2 * Copyright (c) 2010 Isode Limited. 2 * Copyright (c) 2010-2019 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
@@ -17,5 +17,13 @@ namespace Swift {
17 virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0; 17 virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0;
18 virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; 18 virtual void handleEndElement(const std::string& element, const std::string& ns) = 0;
19 virtual void handleCharacterData(const std::string& data) = 0; 19 virtual void handleCharacterData(const std::string& data) = 0;
20
21 /**
22 * Signal that a namespace prefix has been declared
23 * This callback might be called multiple times for a single element,
24 * and will trigger before the corresponding \ref handleStartElement
25 * is called.
26 */
27 virtual void handleNamespaceDeclaration(const std::string& prefix, const std::string& uri);
20 }; 28 };
21} 29}