diff options
13 files changed, 349 insertions, 3 deletions
| diff --git a/Swiften/Elements/RosterItemExchangePayload.cpp b/Swiften/Elements/RosterItemExchangePayload.cpp new file mode 100644 index 0000000..846e184 --- /dev/null +++ b/Swiften/Elements/RosterItemExchangePayload.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "Swiften/Elements/RosterItemExchangePayload.h" +#include "Swiften/Base/foreach.h" + +namespace Swift { + +RosterItemExchangePayload::RosterItemExchangePayload() { +} + +} diff --git a/Swiften/Elements/RosterItemExchangePayload.h b/Swiften/Elements/RosterItemExchangePayload.h new file mode 100644 index 0000000..f573039 --- /dev/null +++ b/Swiften/Elements/RosterItemExchangePayload.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <vector> +#include <string> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> + +#include "Swiften/Elements/Payload.h" +#include "Swiften/JID/JID.h" + + +namespace Swift { +	class RosterItemExchangePayload : public Payload { +		public: +			typedef boost::shared_ptr<RosterItemExchangePayload> ref; + +			enum Action { Add, Modify, Delete }; + +			struct Item { +				Action action; +				JID jid; +				std::string name; +				std::vector<std::string> groups; +			}; + +			typedef std::vector<RosterItemExchangePayload::Item> RosterItemExchangePayloadItems; + +		public: +			RosterItemExchangePayload(); + +			void addItem(const RosterItemExchangePayload::Item& item) { +				items_.push_back(item); +			} + +			const RosterItemExchangePayloadItems& getItems() const { +				return items_; +			} + +		private: +			RosterItemExchangePayloadItems items_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index e20c06d..5052e67 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -17,6 +17,7 @@  #include "Swiften/Parser/PayloadParsers/StartSessionParser.h"  #include "Swiften/Parser/PayloadParsers/StatusParser.h"  #include "Swiften/Parser/PayloadParsers/StatusShowParser.h" +#include "Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h"  #include "Swiften/Parser/PayloadParsers/RosterParser.h"  #include "Swiften/Parser/PayloadParsers/SoftwareVersionParser.h"  #include "Swiften/Parser/PayloadParsers/StorageParser.h" @@ -54,6 +55,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {  	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<ErrorParser>("error")));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<SoftwareVersionParser>("query", "jabber:iq:version")));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<StorageParser>("storage", "storage:bookmarks"))); +	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<RosterItemExchangeParser>("x", "http://jabber.org/protocol/rosterx")));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<RosterParser>("query", "jabber:iq:roster")));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<DiscoInfoParser>("query", "http://jabber.org/protocol/disco#info")));  	factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<DiscoItemsParser>("query", "http://jabber.org/protocol/disco#items"))); diff --git a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp new file mode 100644 index 0000000..7d59cc3 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h" +#include "Swiften/Parser/SerializingParser.h" + +namespace Swift { + +RosterItemExchangeParser::RosterItemExchangeParser() : level_(TopLevel), inItem_(false) { +} + +void RosterItemExchangeParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) { +	if (level_ == PayloadLevel) { +		if (element == "item") { +			inItem_ = true; + +			currentItem_ = RosterItemExchangePayload::Item(); + +			currentItem_.jid = JID(attributes.getAttribute("jid")); +			currentItem_.name = attributes.getAttribute("name"); + +			std::string action = attributes.getAttribute("action"); +			if (action == "add") { +				currentItem_.action = RosterItemExchangePayload::Add; +			} +			else if (action == "modify") { +				currentItem_.action = RosterItemExchangePayload::Modify; +			} +			else if (action == "delete") { +				currentItem_.action = RosterItemExchangePayload::Delete; +			} +			else { +				// Add is default action according to XEP +				currentItem_.action = RosterItemExchangePayload::Add; +			} +		} +	} +	else if (level_ == ItemLevel) { +		if (element == "group") { +			currentText_ = ""; +		} +	} +	++level_; +} + +void RosterItemExchangeParser::handleEndElement(const std::string& element, const std::string& /*ns*/) { +	--level_; +	if (level_ == PayloadLevel) { +		if (inItem_) { +			getPayloadInternal()->addItem(currentItem_); +			inItem_ = false; +		} +	} +	else if (level_ == ItemLevel) { +		if (element == "group") { +			currentItem_.groups.push_back(currentText_); +		} +	} +} + +void RosterItemExchangeParser::handleCharacterData(const std::string& data) { +	currentText_ += data; +} + +} diff --git a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h new file mode 100644 index 0000000..3d6b8f4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include "Swiften/Elements/RosterItemExchangePayload.h" +#include "Swiften/Parser/GenericPayloadParser.h" + +namespace Swift { +	class SerializingParser; + +	class RosterItemExchangeParser : public GenericPayloadParser<RosterItemExchangePayload> { +		public: +			RosterItemExchangeParser(); + +			virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes); +			virtual void handleEndElement(const std::string& element, const std::string&); +			virtual void handleCharacterData(const std::string& data); + +		private: +			enum Level {  +				TopLevel = 0,  +				PayloadLevel = 1, +				ItemLevel = 2 +			}; +			int level_; +			bool inItem_; +			RosterItemExchangePayload::Item currentItem_; +			std::string currentText_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp new file mode 100644 index 0000000..ceba45f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h" + +using namespace Swift; + +class RosterItemExchangeParserTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(RosterItemExchangeParserTest); +		CPPUNIT_TEST(testParse); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testParse() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<x xmlns=\"http://jabber.org/protocol/rosterx\">" +					"<item action=\"add\" jid=\"foo@bar.com\" name=\"Foo @ Bar\">" +						"<group>Group 1</group>" +						"<group>Group 2</group>" +					"</item>" +					"<item action=\"modify\" jid=\"baz@blo.com\" name=\"Baz\"/>" +				"</x>")); + +			RosterItemExchangePayload* payload = dynamic_cast<RosterItemExchangePayload*>(parser.getPayload().get()); +			const RosterItemExchangePayload::RosterItemExchangePayloadItems& items = payload->getItems(); + +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); + +			CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), items[0].jid); +			CPPUNIT_ASSERT_EQUAL(std::string("Foo @ Bar"), items[0].name); +			CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Add, items[0].action); +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].groups.size()); +			CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].groups[0]); +			CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].groups[1]); + +			CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].jid); +			CPPUNIT_ASSERT_EQUAL(std::string("Baz"), items[1].name); +			CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Modify, items[1].action); +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].groups.size()); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(RosterItemExchangeParserTest); diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 2bd5aff..03e4208 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -38,6 +38,7 @@ sources = [  		"PayloadParsers/PrivateStorageParser.cpp",  		"PayloadParsers/RawXMLPayloadParser.cpp",  		"PayloadParsers/ResourceBindParser.cpp", +		"PayloadParsers/RosterItemExchangeParser.cpp",  		"PayloadParsers/RosterParser.cpp",  		"PayloadParsers/SecurityLabelParser.cpp",  		"PayloadParsers/SecurityLabelsCatalogParser.cpp", diff --git a/Swiften/Roster/SetRosterRequest.h b/Swiften/Roster/SetRosterRequest.h index e5ae974..2066089 100644 --- a/Swiften/Roster/SetRosterRequest.h +++ b/Swiften/Roster/SetRosterRequest.h @@ -18,12 +18,12 @@ namespace Swift {  		public:  			typedef boost::shared_ptr<SetRosterRequest> ref; -			static ref create(RosterPayload::ref payload, IQRouter* router) { -				return ref(new SetRosterRequest(payload, router)); +			static ref create(RosterPayload::ref payload, IQRouter* router, const JID& to = JID()) { +				return ref(new SetRosterRequest(payload, router, to));  			}  		private: -			SetRosterRequest(boost::shared_ptr<RosterPayload> payload, IQRouter* router) : Request(IQ::Set, JID(), boost::shared_ptr<RosterPayload>(payload), router) { +			SetRosterRequest(boost::shared_ptr<RosterPayload> payload, IQRouter* router, const JID& to) : Request(IQ::Set, to, boost::shared_ptr<RosterPayload>(payload), router) {  			}  			virtual void handleResponse(boost::shared_ptr<Payload> /*payload*/, ErrorPayload::ref error) { diff --git a/Swiften/SConscript b/Swiften/SConscript index d66bfb3..57c95fc 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -73,6 +73,7 @@ if env["SCONS_STAGE"] == "build" :  			"Elements/Element.cpp",  			"Elements/IQ.cpp",  			"Elements/Payload.cpp", +			"Elements/RosterItemExchangePayload.cpp",  			"Elements/RosterPayload.cpp",  			"Elements/Stanza.cpp",  			"Elements/VCard.cpp", @@ -117,6 +118,7 @@ if env["SCONS_STAGE"] == "build" :  			"Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp",  			"Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp",  			"Serializer/PayloadSerializers/ResourceBindSerializer.cpp", +			"Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp",  			"Serializer/PayloadSerializers/RosterSerializer.cpp",  			"Serializer/PayloadSerializers/SecurityLabelSerializer.cpp",  			"Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp", @@ -235,6 +237,7 @@ if env["SCONS_STAGE"] == "build" :  			File("Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp"), +			File("Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/RosterParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/IBBParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp"), @@ -276,6 +279,7 @@ if env["SCONS_STAGE"] == "build" :  			File("Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp"), +			File("Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp"), diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index 1bbcbf2..0f05580 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -14,6 +14,7 @@  #include "Swiften/Serializer/PayloadSerializers/PrioritySerializer.h"  #include "Swiften/Serializer/PayloadSerializers/ErrorSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/RosterSerializer.h" +#include "Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h"  #include "Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h" @@ -51,6 +52,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {  	serializers_.push_back(new PrioritySerializer());  	serializers_.push_back(new ErrorSerializer());  	serializers_.push_back(new RosterSerializer()); +	serializers_.push_back(new RosterItemExchangeSerializer());  	serializers_.push_back(new MUCPayloadSerializer());  	serializers_.push_back(new MUCUserPayloadSerializer());  	serializers_.push_back(new MUCOwnerPayloadSerializer(this)); diff --git a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp new file mode 100644 index 0000000..76c742c --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h" + +#include <boost/shared_ptr.hpp> + +#include "Swiften/Base/foreach.h" +#include "Swiften/Serializer/XML/XMLTextNode.h" +#include "Swiften/Serializer/XML/XMLRawTextNode.h" +#include "Swiften/Serializer/XML/XMLElement.h" + +namespace Swift { + +RosterItemExchangeSerializer::RosterItemExchangeSerializer() : GenericPayloadSerializer<RosterItemExchangePayload>() { +} + +std::string RosterItemExchangeSerializer::serializePayload(boost::shared_ptr<RosterItemExchangePayload> roster)  const { +	XMLElement queryElement("x", "http://jabber.org/protocol/rosterx"); +	foreach(const RosterItemExchangePayload::Item& item, roster->getItems()) { +		boost::shared_ptr<XMLElement> itemElement(new XMLElement("item")); +		itemElement->setAttribute("jid", item.jid); +		itemElement->setAttribute("name", item.name); + +		switch (item.action) { +			case RosterItemExchangePayload::Add: itemElement->setAttribute("action", "add"); break; +			case RosterItemExchangePayload::Modify: itemElement->setAttribute("action", "modify"); break; +			case RosterItemExchangePayload::Delete: itemElement->setAttribute("action", "delete"); break; +			default: itemElement->setAttribute("action", "add"); break; +		} + +		foreach(const std::string& group, item.groups) { +			boost::shared_ptr<XMLElement> groupElement(new XMLElement("group")); +			groupElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(group))); +			itemElement->addNode(groupElement); +		} + +		queryElement.addNode(itemElement); +	} + +	return queryElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h new file mode 100644 index 0000000..ec2cc13 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include "Swiften/Serializer/GenericPayloadSerializer.h" +#include "Swiften/Elements/RosterItemExchangePayload.h" + +namespace Swift { +	class RosterItemExchangeSerializer : public GenericPayloadSerializer<RosterItemExchangePayload> { +		public: +			RosterItemExchangeSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<RosterItemExchangePayload>)  const; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp new file mode 100644 index 0000000..0fb44c9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h" + +using namespace Swift; + +class RosterItemExchangeSerializerTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(RosterItemExchangeSerializerTest); +		CPPUNIT_TEST(testSerialize); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		RosterItemExchangeSerializerTest() {} + +		void testSerialize() { +			RosterItemExchangeSerializer testling; +			boost::shared_ptr<RosterItemExchangePayload> roster(new RosterItemExchangePayload()); + +			RosterItemExchangePayload::Item item1; +			item1.jid = JID("foo@bar.com"); +			item1.name = "Foo @ Bar"; +			item1.action = RosterItemExchangePayload::Add; +			item1.groups.push_back("Group 1"); +			item1.groups.push_back("Group 2"); +			roster->addItem(item1); + +			RosterItemExchangePayload::Item item2; +			item2.jid = JID("baz@blo.com"); +			item2.name = "Baz"; +			item2.action = RosterItemExchangePayload::Modify; +			roster->addItem(item2); + +			std::string expectedResult =  +				"<x xmlns=\"http://jabber.org/protocol/rosterx\">" +					"<item action=\"add\" jid=\"foo@bar.com\" name=\"Foo @ Bar\">" +						"<group>Group 1</group>" +						"<group>Group 2</group>" +					"</item>" +					"<item action=\"modify\" jid=\"baz@blo.com\" name=\"Baz\"/>" +				"</x>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(RosterItemExchangeSerializerTest); | 
 Swift
 Swift