diff options
-rw-r--r-- | Swiften/Elements/Storage.h | 34 | ||||
-rw-r--r-- | Swiften/Parser/AttributeMap.h | 10 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp | 2 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/StorageParser.cpp | 49 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/StorageParser.h | 27 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/StorageParserFactory.h | 11 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp | 67 | ||||
-rw-r--r-- | Swiften/Parser/UnitTest/AttributeMapTest.cpp | 71 | ||||
-rw-r--r-- | Swiften/SConscript | 3 |
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"), |