summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Elements/Storage.h34
-rw-r--r--Swiften/Parser/AttributeMap.h10
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/StorageParser.cpp49
-rw-r--r--Swiften/Parser/PayloadParsers/StorageParser.h27
-rw-r--r--Swiften/Parser/PayloadParsers/StorageParserFactory.h11
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp67
-rw-r--r--Swiften/Parser/UnitTest/AttributeMapTest.cpp71
-rw-r--r--Swiften/SConscript3
9 files changed, 274 insertions, 0 deletions
diff --git a/Swiften/Elements/Storage.h b/Swiften/Elements/Storage.h
new file mode 100644
index 0000000..00099c5
--- /dev/null
+++ b/Swiften/Elements/Storage.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <vector>
+
+#include "Swiften/Elements/Payload.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
+
+namespace Swift {
+ class Storage : public Payload {
+ public:
+ struct Conference {
+ String name;
+ JID jid;
+ bool autoJoin;
+ String nick;
+ String password;
+ };
+
+ Storage() {
+ }
+
+ const std::vector<Conference>& getConferences() const {
+ return conferences;
+ }
+
+ void addConference(const Conference& conference) {
+ conferences.push_back(conference);
+ }
+
+ private:
+ std::vector<Conference> conferences;
+ };
+}
diff --git a/Swiften/Parser/AttributeMap.h b/Swiften/Parser/AttributeMap.h
index 6662b98..82c839a 100644
--- a/Swiften/Parser/AttributeMap.h
+++ b/Swiften/Parser/AttributeMap.h
@@ -19,6 +19,16 @@ namespace Swift {
return i->second;
}
}
+
+ bool getBoolAttribute(const String& attribute, bool defaultValue = false) const {
+ AttributeMap::const_iterator i = find(attribute);
+ if (i == end()) {
+ return defaultValue;
+ }
+ else {
+ return i->second == "true" || i->second == "1";
+ }
+ }
};
}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index 8a7f468..f4a7b9d 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -11,6 +11,7 @@
#include "Swiften/Parser/PayloadParsers/StatusShowParserFactory.h"
#include "Swiften/Parser/PayloadParsers/RosterParserFactory.h"
#include "Swiften/Parser/PayloadParsers/SoftwareVersionParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StorageParserFactory.h"
#include "Swiften/Parser/PayloadParsers/DiscoInfoParserFactory.h"
#include "Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h"
#include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h"
@@ -29,6 +30,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(shared_ptr<PayloadParserFactory>(new PriorityParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new ErrorParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new SoftwareVersionParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new StorageParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new RosterParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new DiscoInfoParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new ResourceBindParserFactory()));
diff --git a/Swiften/Parser/PayloadParsers/StorageParser.cpp b/Swiften/Parser/PayloadParsers/StorageParser.cpp
new file mode 100644
index 0000000..3eab15e
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StorageParser.cpp
@@ -0,0 +1,49 @@
+#include "Swiften/Parser/PayloadParsers/StorageParser.h"
+
+#include <cassert>
+
+namespace Swift {
+
+StorageParser::StorageParser() : level(TopLevel) {
+}
+
+void StorageParser::handleStartElement(const String& element, const String&, const AttributeMap& attributes) {
+ if (level == BookmarkLevel) {
+ if (element == "conference") {
+ assert(!conference);
+ conference = Storage::Conference();
+ conference->autoJoin = attributes.getBoolAttribute("autojoin", false);
+ conference->jid = JID(attributes.getAttribute("jid"));
+ conference->name = attributes.getAttribute("name");
+ }
+ }
+ else if (level == DetailLevel) {
+ currentText = "";
+ }
+ ++level;
+}
+
+void StorageParser::handleEndElement(const String& element, const String&) {
+ --level;
+ if (level == BookmarkLevel) {
+ if (element == "conference") {
+ assert(conference);
+ getPayloadInternal()->addConference(*conference);
+ conference.reset();
+ }
+ }
+ else if (level == DetailLevel && conference) {
+ if (element == "nick") {
+ conference->nick = currentText;
+ }
+ else if (element == "password") {
+ conference->password = currentText;
+ }
+ }
+}
+
+void StorageParser::handleCharacterData(const String& data) {
+ currentText += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/StorageParser.h b/Swiften/Parser/PayloadParsers/StorageParser.h
new file mode 100644
index 0000000..ad0ab4d
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StorageParser.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include "Swiften/Elements/Storage.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class StorageParser : public GenericPayloadParser<Storage> {
+ public:
+ StorageParser();
+
+ virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+ virtual void handleEndElement(const String& element, const String&);
+ virtual void handleCharacterData(const String& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ BookmarkLevel = 1,
+ DetailLevel = 2
+ };
+ int level;
+ String currentText;
+ boost::optional<Storage::Conference> conference;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/StorageParserFactory.h b/Swiften/Parser/PayloadParsers/StorageParserFactory.h
new file mode 100644
index 0000000..147d178
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/StorageParserFactory.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/StorageParser.h"
+
+namespace Swift {
+ class StorageParserFactory : public GenericPayloadParserFactory<StorageParser> {
+ public:
+ StorageParserFactory() : GenericPayloadParserFactory<StorageParser>("storage", "storage:bookmarks") {}
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
new file mode 100644
index 0000000..fa188b7
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
@@ -0,0 +1,67 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/StorageParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h"
+
+using namespace Swift;
+
+class StorageParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(StorageParserTest);
+ CPPUNIT_TEST(testParse_Conference);
+ CPPUNIT_TEST(testParse_MultipleConferences);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ StorageParserTest() {}
+
+ void testParse_Conference() {
+ StorageParser testling;
+ PayloadParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference "
+ "name='Council of Oberon' "
+ "autojoin='true' jid='council@conference.underhill.org'>"
+ "<nick>Puck</nick>"
+ "<password>MyPass</password>"
+ "</conference>"
+ "</storage>"));
+
+ Storage* payload = dynamic_cast<Storage*>(testling.getPayload().get());
+ std::vector<Storage::Conference> conferences = payload->getConferences();
+ CPPUNIT_ASSERT_EQUAL(1U, conferences.size());
+ CPPUNIT_ASSERT_EQUAL(String("Council of Oberon"), conferences[0].name);
+ CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), conferences[0].jid);
+ CPPUNIT_ASSERT(conferences[0].autoJoin);
+ CPPUNIT_ASSERT_EQUAL(String("Puck"), conferences[0].nick);
+ CPPUNIT_ASSERT_EQUAL(String("MyPass"), conferences[0].password);
+ }
+
+ void testParse_MultipleConferences() {
+ StorageParser testling;
+ PayloadParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<storage xmlns='storage:bookmarks'>"
+ "<conference "
+ "name='Council of Oberon' "
+ "jid='council@conference.underhill.org' />"
+ "<conference "
+ "name='Tea party' "
+ "jid='teaparty@wonderland.lit' />"
+ "</storage>"));
+
+ Storage* payload = dynamic_cast<Storage*>(testling.getPayload().get());
+ std::vector<Storage::Conference> conferences = payload->getConferences();
+ CPPUNIT_ASSERT_EQUAL(2U, conferences.size());
+ CPPUNIT_ASSERT_EQUAL(String("Council of Oberon"), conferences[0].name);
+ CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), conferences[0].jid);
+ CPPUNIT_ASSERT_EQUAL(String("Tea party"), conferences[1].name);
+ CPPUNIT_ASSERT_EQUAL(JID("teaparty@wonderland.lit"), conferences[1].jid);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StorageParserTest);
diff --git a/Swiften/Parser/UnitTest/AttributeMapTest.cpp b/Swiften/Parser/UnitTest/AttributeMapTest.cpp
new file mode 100644
index 0000000..17bda95
--- /dev/null
+++ b/Swiften/Parser/UnitTest/AttributeMapTest.cpp
@@ -0,0 +1,71 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/AttributeMap.h"
+
+using namespace Swift;
+
+class AttributeMapTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(AttributeMapTest);
+ CPPUNIT_TEST(testGetBoolAttribute_True);
+ CPPUNIT_TEST(testGetBoolAttribute_1);
+ CPPUNIT_TEST(testGetBoolAttribute_False);
+ CPPUNIT_TEST(testGetBoolAttribute_0);
+ CPPUNIT_TEST(testGetBoolAttribute_Invalid);
+ CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultTrue);
+ CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultFalse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ AttributeMapTest() {}
+
+ void testGetBoolAttribute_True() {
+ AttributeMap testling;
+ testling["foo"] = "true";
+
+ CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));
+ }
+
+ void testGetBoolAttribute_1() {
+ AttributeMap testling;
+ testling["foo"] = "1";
+
+ CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));
+ }
+
+ void testGetBoolAttribute_False() {
+ AttributeMap testling;
+ testling["foo"] = "false";
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_0() {
+ AttributeMap testling;
+ testling["foo"] = "0";
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_Invalid() {
+ AttributeMap testling;
+ testling["foo"] = "bla";
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_UnknownWithDefaultTrue() {
+ AttributeMap testling;
+
+ CPPUNIT_ASSERT(testling.getBoolAttribute("foo", true));
+ }
+
+ void testGetBoolAttribute_UnknownWithDefaultFalse() {
+ AttributeMap testling;
+
+ CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", false));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AttributeMapTest);
diff --git a/Swiften/SConscript b/Swiften/SConscript
index abd9a44..6a1dde1 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -91,6 +91,7 @@ sources = [
"Parser/PayloadParsers/SecurityLabelParser.cpp",
"Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp",
"Parser/PayloadParsers/SoftwareVersionParser.cpp",
+ "Parser/PayloadParsers/StorageParser.cpp",
"Parser/PayloadParsers/StatusParser.cpp",
"Parser/PayloadParsers/StatusShowParser.cpp",
"Parser/PayloadParsers/VCardParser.cpp",
@@ -226,7 +227,9 @@ env.Append(UNITTEST_SOURCES = [
File("Parser/PayloadParsers/UnitTest/StatusParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/VCardParserTest.cpp"),
+ File("Parser/PayloadParsers/UnitTest/StorageParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp"),
+ File("Parser/UnitTest/AttributeMapTest.cpp"),
File("Parser/UnitTest/IQParserTest.cpp"),
File("Parser/UnitTest/MessageParserTest.cpp"),
File("Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp"),