diff options
| author | Richard Maudsley <richard.maudsley@isode.com> | 2014-02-25 13:19:11 (GMT) | 
|---|---|---|
| committer | Swift Review <review@swift.im> | 2014-04-24 13:06:33 (GMT) | 
| commit | e4704555946626980014d936dcfe6ede2710501b (patch) | |
| tree | 59d0db1bad3d4a0f74c89da8834b2002369c3b4b | |
| parent | 09e9713028b728fad9050c4e20180cc96c4572ce (diff) | |
| download | swift-e4704555946626980014d936dcfe6ede2710501b.zip swift-e4704555946626980014d936dcfe6ede2710501b.tar.bz2 | |
Added MAM parsers, serializers and tests.
Change-Id: I589a7c65664bfecfd0ac34240600dcccb4cbd40e
46 files changed, 1872 insertions, 5 deletions
| diff --git a/Swiften/Elements/Forwarded.cpp b/Swiften/Elements/Forwarded.cpp new file mode 100644 index 0000000..590c1ca --- /dev/null +++ b/Swiften/Elements/Forwarded.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Elements/Forwarded.h> + +using namespace Swift; + +Forwarded::~Forwarded() { +} diff --git a/Swiften/Elements/Forwarded.h b/Swiften/Elements/Forwarded.h new file mode 100644 index 0000000..f1a718c --- /dev/null +++ b/Swiften/Elements/Forwarded.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { +	class Delay; +	class Stanza; + +	class SWIFTEN_API Forwarded : public Payload { +		public: +			virtual ~Forwarded(); + +			void setDelay(boost::shared_ptr<Delay> delay) { delay_ = delay; } +			const boost::shared_ptr<Delay>& getDelay() const { return delay_; } + +			void setStanza(boost::shared_ptr<Stanza> stanza) { stanza_ = stanza; } +			const boost::shared_ptr<Stanza>& getStanza() const { return stanza_; } + +		private: +			boost::shared_ptr<Delay> delay_; +			boost::shared_ptr<Stanza> stanza_; +	}; +} diff --git a/Swiften/Elements/MAMArchived.cpp b/Swiften/Elements/MAMArchived.cpp new file mode 100644 index 0000000..4ec5750 --- /dev/null +++ b/Swiften/Elements/MAMArchived.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Elements/MAMArchived.h> + +using namespace Swift; + +MAMArchived::~MAMArchived() { +} diff --git a/Swiften/Elements/MAMArchived.h b/Swiften/Elements/MAMArchived.h new file mode 100644 index 0000000..df83427 --- /dev/null +++ b/Swiften/Elements/MAMArchived.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> + +namespace Swift { +	class SWIFTEN_API MAMArchived : public Payload { +		public: +			virtual ~MAMArchived(); + +			void setBy(const JID& by) { by_ = by; } +			const JID& getBy() const { return by_; } + +			void setID(const std::string& id) { id_ = id; } +			const std::string& getID() const { return id_; } + +		private: +			JID by_; +			std::string id_; +	}; +} diff --git a/Swiften/Elements/MAMQuery.cpp b/Swiften/Elements/MAMQuery.cpp new file mode 100644 index 0000000..ff71bcc --- /dev/null +++ b/Swiften/Elements/MAMQuery.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Elements/MAMQuery.h> + +using namespace Swift; + +MAMQuery::~MAMQuery() { +} diff --git a/Swiften/Elements/MAMQuery.h b/Swiften/Elements/MAMQuery.h new file mode 100644 index 0000000..3f3724e --- /dev/null +++ b/Swiften/Elements/MAMQuery.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/MAMResult.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/ResultSet.h> + +namespace Swift { +	class SWIFTEN_API MAMQuery : public Payload { +		public: +			virtual ~MAMQuery(); + +			void setQueryID(const boost::optional<std::string>& queryID) { queryID_ = queryID; } +			const boost::optional<std::string>& getQueryID() const { return queryID_; } + +			void setForm(boost::shared_ptr<Form> form) { form_ = form; } +			const boost::shared_ptr<Form>& getForm() const { return form_; } + +			void setResultSet(boost::shared_ptr<ResultSet> resultSet) { resultSet_ = resultSet; } +			const boost::shared_ptr<ResultSet>& getResultSet() const { return resultSet_; } + +		private: +			boost::optional<std::string> queryID_; +			boost::shared_ptr<Form> form_; +			boost::shared_ptr<ResultSet> resultSet_; +	}; +} diff --git a/Swiften/Elements/MAMResult.cpp b/Swiften/Elements/MAMResult.cpp new file mode 100644 index 0000000..79913d3 --- /dev/null +++ b/Swiften/Elements/MAMResult.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Elements/MAMResult.h> + +using namespace Swift; + +MAMResult::~MAMResult() { +} diff --git a/Swiften/Elements/MAMResult.h b/Swiften/Elements/MAMResult.h new file mode 100644 index 0000000..7d43902 --- /dev/null +++ b/Swiften/Elements/MAMResult.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ContainerPayload.h> +#include <Swiften/Elements/Forwarded.h> + +namespace Swift { +	class SWIFTEN_API MAMResult : public ContainerPayload<Forwarded> { +		public: +			virtual ~MAMResult(); + +			void setID(const std::string& id) { id_ = id; } +			const std::string& getID() const { return id_; } + +			void setQueryID(const boost::optional<std::string>& queryID) { queryID_ = queryID; } +			const boost::optional<std::string>& getQueryID() const { return queryID_; } + +		private: +			std::string id_; +			boost::optional<std::string> queryID_; +	}; +} diff --git a/Swiften/Elements/ResultSet.cpp b/Swiften/Elements/ResultSet.cpp new file mode 100644 index 0000000..2565bbb --- /dev/null +++ b/Swiften/Elements/ResultSet.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Elements/ResultSet.h> + +using namespace Swift; + +ResultSet::~ResultSet() { +} diff --git a/Swiften/Elements/ResultSet.h b/Swiften/Elements/ResultSet.h new file mode 100644 index 0000000..871b699 --- /dev/null +++ b/Swiften/Elements/ResultSet.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { +	class SWIFTEN_API ResultSet : public Payload { +		public: +			virtual ~ResultSet(); + +			void setMaxItems(const boost::optional<int>& maxItems) { maxItems_ = maxItems; } +			const boost::optional<int>& getMaxItems() const { return maxItems_; } + +			void setCount(const boost::optional<int>& count) { count_ = count; } +			const boost::optional<int>& getCount() const { return count_; } + +			void setFirstIDIndex(const boost::optional<int>& firstIndex) { firstIndex_ = firstIndex; } +			const boost::optional<int>& getFirstIDIndex() const { return firstIndex_; } + +			void setFirstID(const boost::optional<std::string>& firstID) { firstID_ = firstID; } +			const boost::optional<std::string>& getFirstID() const { return firstID_; } + +			void setLastID(const boost::optional<std::string>& lastID) { lastID_ = lastID; } +			const boost::optional<std::string>& getLastID() const { return lastID_; } + +			void setAfter(const boost::optional<std::string>& after) { after_ = after; } +			const boost::optional<std::string>& getAfter() const { return after_; } + +		private: +			boost::optional<int> maxItems_; +			boost::optional<int> count_; +			boost::optional<int> firstIndex_; +			boost::optional<std::string> firstID_; +			boost::optional<std::string> lastID_; +			boost::optional<std::string> after_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/ForwardedParser.cpp b/Swiften/Parser/PayloadParsers/ForwardedParser.cpp new file mode 100644 index 0000000..6625e77 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ForwardedParser.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/IQParser.h> +#include <Swiften/Parser/MessageParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/DelayParser.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> +#include <Swiften/Parser/PresenceParser.h> + + +using namespace Swift; + +ForwardedParser::ForwardedParser(PayloadParserFactoryCollection* factories) : factories_(factories), level_(TopLevel) { +} + +void ForwardedParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { +	if (level_ == PayloadLevel) { +		if (element == "iq" && ns == "jabber:client") { /* begin parsing a nested stanza? */ +			childParser_ = boost::dynamic_pointer_cast<StanzaParser>(boost::make_shared<IQParser>(factories_)); +		} else if (element == "message" && ns == "jabber:client") { +			childParser_ = boost::dynamic_pointer_cast<StanzaParser>(boost::make_shared<MessageParser>(factories_)); +		} else if (element == "presence" && ns == "jabber:client") { +			childParser_ = boost::dynamic_pointer_cast<StanzaParser>(boost::make_shared<PresenceParser>(factories_)); +		} else if (element == "delay" && ns == "urn:xmpp:delay") { /* nested delay payload */ +			delayParser_ = boost::make_shared<DelayParser>(); +		} +	} +	if (childParser_) { /* parsing a nested stanza? */ +		childParser_->handleStartElement(element, ns, attributes); +	} +	if (delayParser_) { /* parsing a nested delay payload? */ +		delayParser_->handleStartElement(element, ns, attributes); +	} +	++level_; +} + +void ForwardedParser::handleEndElement(const std::string& element, const std::string& ns) { +	--level_; +	if (childParser_ && level_ >= PayloadLevel) { +		childParser_->handleEndElement(element, ns); +	} +	if (childParser_ && level_ == PayloadLevel) { +		/* done parsing nested stanza */ +		getPayloadInternal()->setStanza(childParser_->getStanza()); +		childParser_.reset(); +	} +	if (delayParser_ && level_ >= PayloadLevel) { +		delayParser_->handleEndElement(element, ns); +	} +	if (delayParser_ && level_ == PayloadLevel) { +		/* done parsing nested delay payload */ +		getPayloadInternal()->setDelay(boost::dynamic_pointer_cast<Delay>(delayParser_->getPayload())); +		delayParser_.reset(); +	} +} + +void ForwardedParser::handleCharacterData(const std::string& data) { +	if (childParser_) { +		childParser_->handleCharacterData(data); +	} +	if (delayParser_) { +		delayParser_->handleCharacterData(data); +	} +} diff --git a/Swiften/Parser/PayloadParsers/ForwardedParser.h b/Swiften/Parser/PayloadParsers/ForwardedParser.h new file mode 100644 index 0000000..14117ae --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ForwardedParser.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { +	class PayloadParserFactoryCollection; +	class StanzaParser; +	class DelayParser; + +	class SWIFTEN_API ForwardedParser : public GenericPayloadParser<Forwarded> { +		public: +			ForwardedParser(PayloadParserFactoryCollection* factories); + +			virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) SWIFTEN_OVERRIDE; +			virtual void handleEndElement(const std::string& element, const std::string&) SWIFTEN_OVERRIDE; +			virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE; + +			enum Level { +				TopLevel = 0, +				PayloadLevel = 1 +			}; + +		private: +			PayloadParserFactoryCollection* factories_; +			boost::shared_ptr<StanzaParser> childParser_; +			boost::shared_ptr<DelayParser> delayParser_; +			int level_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index 22019b4..4541b3b 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -76,6 +76,11 @@  #include <Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h>  #include <Swiften/Parser/PayloadParsers/UserLocationParser.h>  #include <Swiften/Parser/PayloadParsers/UserTuneParser.h> +#include <Swiften/Parser/PayloadParsers/ResultSetParser.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> +#include <Swiften/Parser/PayloadParsers/MAMResultParser.h> +#include <Swiften/Parser/PayloadParsers/MAMQueryParser.h> +#include <Swiften/Parser/PayloadParsers/MAMArchivedParser.h>  using namespace boost; @@ -144,6 +149,11 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<PubSubOwnerPubSubParser> >("pubsub", "http://jabber.org/protocol/pubsub#owner", this));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<PubSubEventParser> >("event", "http://jabber.org/protocol/pubsub#event", this));  	factories_.push_back(boost::make_shared<PubSubErrorParserFactory>()); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<ResultSetParser> >("set", "http://jabber.org/protocol/rsm")); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<ForwardedParser> >("forwarded", "urn:xmpp:forward:0", this)); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<MAMResultParser> >("result", "urn:xmpp:mam:0", this)); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MAMQueryParser> >("query", "urn:xmpp:mam:0")); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MAMArchivedParser> >("archived", "urn:xmpp:mam:0"));  	foreach(shared_ptr<PayloadParserFactory> factory, factories_) {  		addFactory(factory.get()); diff --git a/Swiften/Parser/PayloadParsers/MAMArchivedParser.cpp b/Swiften/Parser/PayloadParsers/MAMArchivedParser.cpp new file mode 100644 index 0000000..616d41a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMArchivedParser.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/MAMArchivedParser.h> + +using namespace Swift; + +MAMArchivedParser::MAMArchivedParser() : level_(TopLevel) { +} + +void MAMArchivedParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { +	if (level_ == TopLevel) { +		boost::optional<std::string> attributeValue; +		if ((attributeValue = attributes.getAttributeValue("by"))) { +			getPayloadInternal()->setBy(*attributeValue); +		} +		if ((attributeValue = attributes.getAttributeValue("id"))) { +			getPayloadInternal()->setID(*attributeValue); +		} +	} + +	++level_; +} + +void MAMArchivedParser::handleEndElement(const std::string&, const std::string&) { +	--level_; +} + +void MAMArchivedParser::handleCharacterData(const std::string&) { +} diff --git a/Swiften/Parser/PayloadParsers/MAMArchivedParser.h b/Swiften/Parser/PayloadParsers/MAMArchivedParser.h new file mode 100644 index 0000000..b92b41a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMArchivedParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMArchived.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { +	class PayloadParserFactoryCollection; + +	class SWIFTEN_API MAMArchivedParser : public GenericPayloadParser<MAMArchived> { +		public: +			MAMArchivedParser(); + +			virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) SWIFTEN_OVERRIDE; +			virtual void handleEndElement(const std::string& element, const std::string&) SWIFTEN_OVERRIDE; +			virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE; + +			enum Level { +				TopLevel = 0 +			}; + +		private: +			int level_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/MAMQueryParser.cpp b/Swiften/Parser/PayloadParsers/MAMQueryParser.cpp new file mode 100644 index 0000000..9ae8e41 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMQueryParser.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> +#include <Swiften/Parser/PayloadParsers/ResultSetParser.h> +#include <Swiften/Parser/PayloadParsers/MAMQueryParser.h> + +using namespace Swift; + +MAMQueryParser::MAMQueryParser() : level_(TopLevel) { +} + +void MAMQueryParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { +	if (level_ == TopLevel) { +		boost::optional<std::string> attributeValue; +		if ((attributeValue = attributes.getAttributeValue("queryid"))) { +			getPayloadInternal()->setQueryID(*attributeValue); +		} +	} else if (level_ == PayloadLevel) { +		if (element == "x" && ns == "jabber:x:data") { +			formParser_ = boost::make_shared<FormParser>(); +		} else if (element == "set" && ns == "http://jabber.org/protocol/rsm") { +			resultSetParser_ = boost::make_shared<ResultSetParser>(); +		} +	} + +	if (formParser_) { /* parsing a nested Form */ +		formParser_->handleStartElement(element, ns, attributes); +	} + +	if (resultSetParser_) { /* parsing a nested ResultSet */ +		resultSetParser_->handleStartElement(element, ns, attributes); +	} + +	++level_; +} + +void MAMQueryParser::handleEndElement(const std::string& element, const std::string& ns) { +	--level_; + +	if (formParser_ && level_ >= PayloadLevel) { +		formParser_->handleEndElement(element, ns); +	} +	if (formParser_ && level_ == PayloadLevel) { +		/* done parsing nested Form */ +		getPayloadInternal()->setForm(boost::dynamic_pointer_cast<Form>(formParser_->getPayload())); +		formParser_.reset(); +	} + +	if (resultSetParser_ && level_ >= PayloadLevel) { +		resultSetParser_->handleEndElement(element, ns); +	} +	if (resultSetParser_ && level_ == PayloadLevel) { +		/* done parsing nested ResultSet */ +		getPayloadInternal()->setResultSet(boost::dynamic_pointer_cast<ResultSet>(resultSetParser_->getPayload())); +		resultSetParser_.reset(); +	} +} + +void MAMQueryParser::handleCharacterData(const std::string& data) { +	if (formParser_) { +		formParser_->handleCharacterData(data); +	} +	if (resultSetParser_) { +		resultSetParser_->handleCharacterData(data); +	} +} diff --git a/Swiften/Parser/PayloadParsers/MAMQueryParser.h b/Swiften/Parser/PayloadParsers/MAMQueryParser.h new file mode 100644 index 0000000..7bbdacb --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMQueryParser.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMQuery.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { +	class PayloadParserFactoryCollection; +	class ResultSetParser; +	class FormParser; + +	class SWIFTEN_API MAMQueryParser : public GenericPayloadParser<MAMQuery> { +		public: +			MAMQueryParser(); + +			virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) SWIFTEN_OVERRIDE; +			virtual void handleEndElement(const std::string& element, const std::string&) SWIFTEN_OVERRIDE; +			virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE; + +			enum Level { +				TopLevel = 0,  +				PayloadLevel = 1 +			}; + +		private: +			boost::shared_ptr<FormParser> formParser_; +			boost::shared_ptr<ResultSetParser> resultSetParser_; +			int level_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/MAMResultParser.cpp b/Swiften/Parser/PayloadParsers/MAMResultParser.cpp new file mode 100644 index 0000000..e4eec3b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMResultParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> +#include <Swiften/Parser/PayloadParsers/MAMResultParser.h> + +using namespace Swift; + +MAMResultParser::MAMResultParser(PayloadParserFactoryCollection* factories) : factories_(factories), level_(TopLevel) { +} + +void MAMResultParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { +	if (level_ == TopLevel) { +		boost::optional<std::string> attributeValue; +		if ((attributeValue = attributes.getAttributeValue("id"))) { +			getPayloadInternal()->setID(*attributeValue); +		} +		if ((attributeValue = attributes.getAttributeValue("queryid"))) { +			getPayloadInternal()->setQueryID(*attributeValue); +		} +	} else if (level_ == PayloadLevel) { +		if (element == "forwarded" && ns == "urn:xmpp:forward:0") { +			payloadParser_ = boost::make_shared<ForwardedParser>(factories_); +		} +	} + +	if (payloadParser_) { +		/* parsing a nested payload */ +		payloadParser_->handleStartElement(element, ns, attributes); +	} + +	++level_; +} + +void MAMResultParser::handleEndElement(const std::string& element, const std::string& ns) { +	--level_; +	if (payloadParser_ && level_ >= PayloadLevel) { +		payloadParser_->handleEndElement(element, ns); +	} +	if (payloadParser_ && level_ == PayloadLevel) { +		/* done parsing nested stanza */ +		getPayloadInternal()->setPayload(boost::dynamic_pointer_cast<Forwarded>(payloadParser_->getPayload())); +		payloadParser_.reset(); +	} +} + +void MAMResultParser::handleCharacterData(const std::string& data) { +	if (payloadParser_) { +		payloadParser_->handleCharacterData(data); +	} +} diff --git a/Swiften/Parser/PayloadParsers/MAMResultParser.h b/Swiften/Parser/PayloadParsers/MAMResultParser.h new file mode 100644 index 0000000..39ff20a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMResultParser.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMResult.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { +	class PayloadParserFactoryCollection; +	class ForwardedParser; + +	class SWIFTEN_API MAMResultParser : public GenericPayloadParser<MAMResult> { +		public: +			MAMResultParser(PayloadParserFactoryCollection* factories); + +			virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) SWIFTEN_OVERRIDE; +			virtual void handleEndElement(const std::string& element, const std::string&) SWIFTEN_OVERRIDE; +			virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE; + +			enum Level { +				TopLevel = 0,  +				PayloadLevel = 1 +			}; + +		private: +			boost::shared_ptr<ForwardedParser> payloadParser_; +			PayloadParserFactoryCollection* factories_; +			int level_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/ResultSetParser.cpp b/Swiften/Parser/PayloadParsers/ResultSetParser.cpp new file mode 100644 index 0000000..95960d7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ResultSetParser.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/ResultSetParser.h> +#include <boost/optional.hpp> +#include <boost/lexical_cast.hpp> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> + +using namespace Swift; + +ResultSetParser::ResultSetParser() : level_(TopLevel) { +} + +void ResultSetParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { +	currentText_ = ""; +	if (level_ == PayloadLevel) { +		if (element == "first" && ns == "http://jabber.org/protocol/rsm") { +			if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("index")) { +				try { +					getPayloadInternal()->setFirstIDIndex(boost::lexical_cast<int>(*attributeValue)); +				} catch(boost::bad_lexical_cast&) { +				} +			} +		} +	} +	++level_; +} + +void ResultSetParser::handleEndElement(const std::string& element, const std::string&) { +	--level_; +	if (level_ == PayloadLevel) { +		if (element == "max") { +			try { +				getPayloadInternal()->setMaxItems(boost::lexical_cast<int>(currentText_)); +			} catch(boost::bad_lexical_cast&) { +			} +		} else if (element == "count") { +			try { +				getPayloadInternal()->setCount(boost::lexical_cast<int>(currentText_)); +			} catch(boost::bad_lexical_cast&) { +			} +		} else if (element == "first") { +			getPayloadInternal()->setFirstID(currentText_); +		} else if (element == "last") { +			getPayloadInternal()->setLastID(currentText_); +		} else if (element == "after") { +			getPayloadInternal()->setAfter(currentText_); +		} +	} +} + +void ResultSetParser::handleCharacterData(const std::string& data) { +	currentText_ += data; +} diff --git a/Swiften/Parser/PayloadParsers/ResultSetParser.h b/Swiften/Parser/PayloadParsers/ResultSetParser.h new file mode 100644 index 0000000..55399ef --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ResultSetParser.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ResultSet.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { +	class PayloadParserFactoryCollection; + +	class SWIFTEN_API ResultSetParser : public GenericPayloadParser<ResultSet> { +		public: +			ResultSetParser(); + +			virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) SWIFTEN_OVERRIDE; +			virtual void handleEndElement(const std::string& element, const std::string&) SWIFTEN_OVERRIDE; +			virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE; + +			enum Level { +				TopLevel = 0,  +				PayloadLevel = 1 +			}; + +		private: +			std::string currentText_; +			int level_; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp new file mode 100644 index 0000000..a950fa4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> + +using namespace Swift; + +class ForwardedParserTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(ForwardedParserTest); +		CPPUNIT_TEST(testParseIQ); +		CPPUNIT_TEST(testParseMessage); +		CPPUNIT_TEST(testParseMessageNoDelay); +		CPPUNIT_TEST(testParsePresence); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testParseIQ() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<delay xmlns=\"urn:xmpp:delay\" stamp=\"2010-07-10T23:08:25Z\"/>" +					"<iq xmlns=\"jabber:client\" type=\"get\" from=\"kindanormal@example.com/IM\" to=\"stupidnewbie@example.com\" id=\"id0\"/>" +				"</forwarded>")); + +			boost::shared_ptr<Forwarded> payload = parser.getPayload<Forwarded>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getDelay()); +			CPPUNIT_ASSERT_EQUAL(std::string("2010-07-10T23:08:25Z"), dateTimeToString(payload->getDelay()->getStamp())); + +			boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(payload->getStanza()); +			CPPUNIT_ASSERT(!!iq); +			CPPUNIT_ASSERT_EQUAL(JID("stupidnewbie@example.com"), iq->getTo()); +			CPPUNIT_ASSERT_EQUAL(JID("kindanormal@example.com/IM"), iq->getFrom()); +			CPPUNIT_ASSERT_EQUAL(std::string("id0"), iq->getID()); +			CPPUNIT_ASSERT_EQUAL(IQ::Get, iq->getType()); +		} + +		void testParseMessage() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<delay xmlns=\"urn:xmpp:delay\" stamp=\"2010-07-10T23:08:25Z\"/>" +					"<message xmlns=\"jabber:client\" to=\"juliet@capulet.lit/balcony\" from=\"romeo@montague.lit/orchard\" type=\"chat\">" +						"<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>" +					"</message>" +				"</forwarded>")); + +			boost::shared_ptr<Forwarded> payload = parser.getPayload<Forwarded>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getDelay()); +			CPPUNIT_ASSERT_EQUAL(std::string("2010-07-10T23:08:25Z"), dateTimeToString(payload->getDelay()->getStamp())); + +			boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(payload->getStanza()); +			CPPUNIT_ASSERT(!!message); +			const std::string expectedBody = "Call me but love, and I'll be new baptized; Henceforth I never will be Romeo."; +			CPPUNIT_ASSERT_EQUAL(expectedBody, message->getBody()); +			CPPUNIT_ASSERT_EQUAL(Message::Chat, message->getType()); +			CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), message->getTo()); +			CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), message->getFrom()); +		} + +		void testParseMessageNoDelay() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<message xmlns=\"jabber:client\" to=\"juliet@capulet.lit/balcony\" from=\"romeo@montague.lit/orchard\" type=\"chat\">" +						"<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>" +					"</message>" +				"</forwarded>")); + +			boost::shared_ptr<Forwarded> payload = parser.getPayload<Forwarded>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(!payload->getDelay()); + +			boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(payload->getStanza()); +			CPPUNIT_ASSERT(!!message); +			const std::string expectedBody = "Call me but love, and I'll be new baptized; Henceforth I never will be Romeo."; +			CPPUNIT_ASSERT_EQUAL(expectedBody, message->getBody()); +			CPPUNIT_ASSERT_EQUAL(Message::Chat, message->getType()); +			CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), message->getTo()); +			CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), message->getFrom()); +		} + +		void testParsePresence() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<delay xmlns=\"urn:xmpp:delay\" stamp=\"2010-07-10T23:08:25Z\"/>" +					"<presence xmlns=\"jabber:client\" from=\"alice@wonderland.lit/rabbithole\" to=\"madhatter@wonderland.lit\" type=\"unavailable\"/>" +				"</forwarded>")); + +			boost::shared_ptr<Forwarded> payload = parser.getPayload<Forwarded>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getDelay()); +			CPPUNIT_ASSERT_EQUAL(std::string("2010-07-10T23:08:25Z"), dateTimeToString(payload->getDelay()->getStamp())); + +			boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(payload->getStanza()); +			CPPUNIT_ASSERT(!!presence); +			CPPUNIT_ASSERT_EQUAL(JID("madhatter@wonderland.lit"), presence->getTo()); +			CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/rabbithole"), presence->getFrom()); +			CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, presence->getType()); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ForwardedParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MAMArchivedParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MAMArchivedParserTest.cpp new file mode 100644 index 0000000..3e65cc6 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MAMArchivedParserTest.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParsers/MAMArchivedParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class MAMArchivedParserTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(MAMArchivedParserTest); +		CPPUNIT_TEST(testParse); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testParse() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<archived by=\"juliet@capulet.lit\" id=\"28482-98726-73623\" xmlns=\"urn:xmpp:mam:0\"/>")); + +			boost::shared_ptr<MAMArchived> payload = parser.getPayload<MAMArchived>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit"), payload->getBy()); +			CPPUNIT_ASSERT_EQUAL(std::string("28482-98726-73623"), payload->getID()); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMArchivedParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp new file mode 100644 index 0000000..ddcd7c4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParsers/MAMQueryParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class MAMQueryParserTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(MAMQueryParserTest); +		CPPUNIT_TEST(testParse); +		CPPUNIT_TEST(testParseEmpty); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testParse() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<query queryid=\"id0\" xmlns=\"urn:xmpp:mam:0\">" +					"<x type=\"form\" xmlns=\"jabber:x:data\">" +						"<field type=\"text-single\" var=\"FORM_TYPE\">" +							"<value>urn:xmpp:mam:0</value>" +						"</field>" +						"<field type=\"text-single\" var=\"start\">" +							"<value>2010-08-07T00:00:00Z</value>" +						"</field>" +					"</x>" +					"<set xmlns=\"http://jabber.org/protocol/rsm\">" +						"<max>10</max>" +					"</set>" +				"</query>")); + + +			boost::shared_ptr<MAMQuery> payload = parser.getPayload<MAMQuery>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getQueryID()); +			CPPUNIT_ASSERT_EQUAL(std::string("id0"), *payload->getQueryID()); + +			CPPUNIT_ASSERT(payload->getForm()); +			boost::shared_ptr<FormField> fieldType = payload->getForm()->getField("FORM_TYPE"); +			CPPUNIT_ASSERT(fieldType); +			CPPUNIT_ASSERT_EQUAL(std::string("urn:xmpp:mam:0"), fieldType->getTextSingleValue()); +			boost::shared_ptr<FormField> fieldStart = payload->getForm()->getField("start"); +			CPPUNIT_ASSERT(fieldStart); +			CPPUNIT_ASSERT_EQUAL(std::string("2010-08-07T00:00:00Z"), fieldStart->getTextSingleValue()); + +			CPPUNIT_ASSERT(payload->getResultSet()); +			boost::shared_ptr<ResultSet> resultSet = payload->getResultSet(); +			CPPUNIT_ASSERT(resultSet->getMaxItems()); +			CPPUNIT_ASSERT_EQUAL(*resultSet->getMaxItems(), 10); +		} + +		void testParseEmpty() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<query queryid=\"id0\" xmlns=\"urn:xmpp:mam:0\">" +				"</query>")); + +			boost::shared_ptr<MAMQuery> payload = parser.getPayload<MAMQuery>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getQueryID()); +			CPPUNIT_ASSERT_EQUAL(std::string("id0"), *payload->getQueryID()); +			CPPUNIT_ASSERT(!payload->getForm()); +			CPPUNIT_ASSERT(!payload->getResultSet()); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMQueryParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp new file mode 100644 index 0000000..e62db9b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParsers/MAMResultParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/Message.h> + +using namespace Swift; + +class MAMResultParserTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(MAMResultParserTest); +		CPPUNIT_TEST(testParse); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testParse() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<result id=\"28482-98726-73623\" queryid=\"f27\" xmlns=\"urn:xmpp:mam:0\">" +					"<forwarded xmlns=\"urn:xmpp:forward:0\">" +						"<delay stamp=\"2010-07-10T23:08:25Z\" xmlns=\"urn:xmpp:delay\"/>" +						"<message xmlns=\"jabber:client\" from=\"romeo@montague.lit/orchard\" to=\"juliet@capulet.lit/balcony\" type=\"chat\">" +							"<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>" +						"</message>" +					"</forwarded>" +				"</result>")); + +			boost::shared_ptr<MAMResult> payload = parser.getPayload<MAMResult>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT_EQUAL(std::string("28482-98726-73623"), payload->getID()); +			CPPUNIT_ASSERT(payload->getQueryID()); +			CPPUNIT_ASSERT_EQUAL(std::string("f27"), *payload->getQueryID()); + +			boost::shared_ptr<Forwarded> forwarded = payload->getPayload(); +			CPPUNIT_ASSERT(forwarded->getDelay()); +			CPPUNIT_ASSERT_EQUAL(std::string("2010-07-10T23:08:25Z"), dateTimeToString(forwarded->getDelay()->getStamp())); + +			boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(forwarded->getStanza()); +			CPPUNIT_ASSERT(!!message); +			const std::string expectedBody = "Call me but love, and I'll be new baptized; Henceforth I never will be Romeo."; +			CPPUNIT_ASSERT_EQUAL(expectedBody, message->getBody()); +			CPPUNIT_ASSERT_EQUAL(Message::Chat, message->getType()); +			CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), message->getTo()); +			CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), message->getFrom()); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMResultParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp new file mode 100644 index 0000000..68df71b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Parser/PayloadParsers/ResultSetParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class ResultSetParserTest : public CppUnit::TestFixture +{ +		CPPUNIT_TEST_SUITE(ResultSetParserTest); +		CPPUNIT_TEST(testParse); +		CPPUNIT_TEST(testParseFirstNoIndex); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testParse() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<set xmlns=\"http://jabber.org/protocol/rsm\">" +					"<max>100</max>" +					"<count>800</count>" +					"<first index=\"123\">stpeter@jabber.org</first>" +					"<last>peterpan@neverland.lit</last>" +					"<after>09af3-cc343-b409f</after>" +				"</set>")); + +			boost::shared_ptr<ResultSet> payload = parser.getPayload<ResultSet>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getMaxItems()); +			CPPUNIT_ASSERT_EQUAL(100, *payload->getMaxItems()); +			CPPUNIT_ASSERT(payload->getCount()); +			CPPUNIT_ASSERT_EQUAL(800, *payload->getCount()); +			CPPUNIT_ASSERT(payload->getFirstID()); +			CPPUNIT_ASSERT_EQUAL(std::string("stpeter@jabber.org"), *payload->getFirstID()); +			CPPUNIT_ASSERT(payload->getFirstIDIndex()); +			CPPUNIT_ASSERT_EQUAL(123, *payload->getFirstIDIndex()); +			CPPUNIT_ASSERT(payload->getLastID()); +			CPPUNIT_ASSERT_EQUAL(std::string("peterpan@neverland.lit"), *payload->getLastID()); +			CPPUNIT_ASSERT(payload->getAfter()); +			CPPUNIT_ASSERT_EQUAL(std::string("09af3-cc343-b409f"), *payload->getAfter()); +		} + +		void testParseFirstNoIndex() { +			PayloadsParserTester parser; +			CPPUNIT_ASSERT(parser.parse( +				"<set xmlns=\"http://jabber.org/protocol/rsm\">" +					"<first>stpeter@jabber.org</first>" +				"</set>")); + +			boost::shared_ptr<ResultSet> payload = parser.getPayload<ResultSet>(); +			CPPUNIT_ASSERT(!!payload); +			CPPUNIT_ASSERT(payload->getFirstID()); +			CPPUNIT_ASSERT_EQUAL(std::string("stpeter@jabber.org"), *payload->getFirstID()); +			CPPUNIT_ASSERT(!payload->getFirstIDIndex()); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ResultSetParserTest); diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 4d6db11..056862f 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -77,6 +77,11 @@ sources = [  		"PayloadParsers/UserTuneParser.cpp",  		"PayloadParsers/WhiteboardParser.cpp",  		"PayloadParsers/PubSubErrorParserFactory.cpp", +		"PayloadParsers/ResultSetParser.cpp", +		"PayloadParsers/ForwardedParser.cpp", +		"PayloadParsers/MAMResultParser.cpp", +		"PayloadParsers/MAMQueryParser.cpp", +		"PayloadParsers/MAMArchivedParser.cpp",  		"PlatformXMLParserFactory.cpp",  		"PresenceParser.cpp",  		"SerializingParser.cpp", diff --git a/Swiften/SConscript b/Swiften/SConscript index 80db7da..574b7d8 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -141,6 +141,11 @@ if env["SCONS_STAGE"] == "build" :  			"Elements/UserTune.cpp",  			"Elements/VCard.cpp",  			"Elements/MUCOccupant.cpp", +			"Elements/ResultSet.cpp", +			"Elements/Forwarded.cpp", +			"Elements/MAMResult.cpp", +			"Elements/MAMQuery.cpp", +			"Elements/MAMArchived.cpp",  			"Entity/Entity.cpp",  			"Entity/PayloadPersister.cpp",  			"MUC/MUC.cpp", @@ -219,6 +224,11 @@ if env["SCONS_STAGE"] == "build" :  			"Serializer/PayloadSerializers/UserLocationSerializer.cpp",  			"Serializer/PayloadSerializers/UserTuneSerializer.cpp",  			"Serializer/PayloadSerializers/WhiteboardSerializer.cpp", +			"Serializer/PayloadSerializers/ResultSetSerializer.cpp", +			"Serializer/PayloadSerializers/ForwardedSerializer.cpp", +			"Serializer/PayloadSerializers/MAMResultSerializer.cpp", +			"Serializer/PayloadSerializers/MAMQuerySerializer.cpp", +			"Serializer/PayloadSerializers/MAMArchivedSerializer.cpp",  			"Serializer/PresenceSerializer.cpp",  			"Serializer/StanzaSerializer.cpp",  			"Serializer/StreamErrorSerializer.cpp", @@ -407,6 +417,11 @@ if env["SCONS_STAGE"] == "build" :  			File("Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp"),  			File("Parser/PayloadParsers/UnitTest/IdleParserTest.cpp"), +			File("Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp"), +			File("Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp"), +			File("Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp"), +			File("Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp"), +			File("Parser/PayloadParsers/UnitTest/MAMArchivedParserTest.cpp"),  			File("Parser/UnitTest/BOSHBodyExtractorTest.cpp"),  			File("Parser/UnitTest/AttributeMapTest.cpp"),  			File("Parser/UnitTest/EnumParserTest.cpp"), @@ -459,6 +474,11 @@ if env["SCONS_STAGE"] == "build" :  			File("Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp"),  			File("Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp"), +			File("Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp"), +			File("Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp"), +			File("Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp"), +			File("Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp"), +			File("Serializer/PayloadSerializers/UnitTest/MAMArchivedSerializerTest.cpp"),  			File("Serializer/UnitTest/StreamFeaturesSerializerTest.cpp"),  			File("Serializer/UnitTest/AuthSuccessSerializerTest.cpp"),  			File("Serializer/UnitTest/AuthChallengeSerializerTest.cpp"), diff --git a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp index 6148632..f809798 100644 --- a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp @@ -20,7 +20,7 @@ DelaySerializer::DelaySerializer() : GenericPayloadSerializer<Delay>() {  std::string DelaySerializer::serializePayload(boost::shared_ptr<Delay> delay)  const {  	XMLElement delayElement("delay", "urn:xmpp:delay"); -	if (delay->getFrom()) { +	if (delay->getFrom() && delay->getFrom()->isValid()) {  		delayElement.setAttribute("from", delay->getFrom()->toString());  	}  	delayElement.setAttribute("stamp", dateTimeToString(delay->getStamp())); diff --git a/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.cpp new file mode 100644 index 0000000..767d9de --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/GenericStanzaSerializer.h> +#include <Swiften/Serializer/IQSerializer.h> +#include <Swiften/Serializer/MessageSerializer.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/DelaySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/PresenceSerializer.h> + + +using namespace Swift; + +ForwardedSerializer::ForwardedSerializer(PayloadSerializerCollection* serializers) : serializers_(serializers) { +} + +ForwardedSerializer::~ForwardedSerializer() { +} + +std::string ForwardedSerializer::serializePayload(boost::shared_ptr<Forwarded> payload) const { +	if (!payload) { +		return ""; +	} + +	XMLElement element("forwarded", "urn:xmpp:forward:0"); + +	if (payload->getDelay()) { +		element.addNode(boost::make_shared<XMLRawTextNode>(DelaySerializer().serialize(payload->getDelay()))); +	} + +	if (payload->getStanza()) { /* find out what type of stanza we are dealing with and branch into the correct serializer*/ +		boost::shared_ptr<IQ> iq; +		boost::shared_ptr<Message> message; +		boost::shared_ptr<Presence> presence; +		const std::string ns = "jabber:client"; +		if ((iq = boost::dynamic_pointer_cast<IQ>(payload->getStanza()))) { +			element.addNode(boost::make_shared<XMLRawTextNode>(safeByteArrayToString(IQSerializer(serializers_).serialize(iq, ns)))); +		} else if ((message = boost::dynamic_pointer_cast<Message>(payload->getStanza()))) { +			element.addNode(boost::make_shared<XMLRawTextNode>(safeByteArrayToString(MessageSerializer(serializers_).serialize(message, ns)))); +		} else if ((presence = boost::dynamic_pointer_cast<Presence>(payload->getStanza()))) { +			element.addNode(boost::make_shared<XMLRawTextNode>(safeByteArrayToString(PresenceSerializer(serializers_).serialize(presence, ns)))); +		} +	} + +	return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h new file mode 100644 index 0000000..4b283e2 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { +	class PayloadSerializerCollection; + +	class SWIFTEN_API ForwardedSerializer : public GenericPayloadSerializer<Forwarded> { +		public: +			ForwardedSerializer(PayloadSerializerCollection* serializers); +			virtual ~ForwardedSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<Forwarded>) const SWIFTEN_OVERRIDE; + +		private: +			PayloadSerializerCollection* serializers_; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.cpp new file mode 100644 index 0000000..04a6584 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.h> + +using namespace Swift; + +MAMArchivedSerializer::MAMArchivedSerializer(PayloadSerializerCollection* serializers) : serializers_(serializers) { +} + +MAMArchivedSerializer::~MAMArchivedSerializer() { +} + +std::string MAMArchivedSerializer::serializePayload(boost::shared_ptr<MAMArchived> payload) const { +	if (!payload) { +		return ""; +	} + +	XMLElement element("archived", "urn:xmpp:mam:0"); +	element.setAttribute("by", payload->getBy()); +	element.setAttribute("id", payload->getID()); + +	return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.h b/Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.h new file mode 100644 index 0000000..7c60798 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMArchived.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { +	class PayloadSerializerCollection; + +	class SWIFTEN_API MAMArchivedSerializer : public GenericPayloadSerializer<MAMArchived> { +		public: +			MAMArchivedSerializer(PayloadSerializerCollection* serializers); +			virtual ~MAMArchivedSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<MAMArchived>) const SWIFTEN_OVERRIDE; + +		private: +			PayloadSerializerCollection* serializers_; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.cpp b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.cpp new file mode 100644 index 0000000..1151fba --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> + +using namespace Swift; + +MAMQuerySerializer::MAMQuerySerializer(PayloadSerializerCollection* serializers) : serializers_(serializers) { +} + +MAMQuerySerializer::~MAMQuerySerializer() { +} + +std::string MAMQuerySerializer::serializePayload(boost::shared_ptr<MAMQuery> payload) const { +	if (!payload) { +		return ""; +	} + +	XMLElement element("query", "urn:xmpp:mam:0"); + +	if (payload->getQueryID()) { +		element.setAttribute("queryid", *payload->getQueryID()); +	} + +	if (payload->getForm()) { +		element.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getForm()))); +	} + +	if (payload->getResultSet()) { +		element.addNode(boost::make_shared<XMLRawTextNode>(ResultSetSerializer().serialize(payload->getResultSet()))); +	} + +	return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h new file mode 100644 index 0000000..a6d1339 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMQuery.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { +	class PayloadSerializerCollection; + +	class SWIFTEN_API MAMQuerySerializer : public GenericPayloadSerializer<MAMQuery> { +		public: +			MAMQuerySerializer(PayloadSerializerCollection* serializers); +			virtual ~MAMQuerySerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<MAMQuery>) const SWIFTEN_OVERRIDE; + +		private: +			PayloadSerializerCollection* serializers_; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.cpp new file mode 100644 index 0000000..c4fd4a5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h> + +using namespace Swift; + +MAMResultSerializer::MAMResultSerializer(PayloadSerializerCollection* serializers) : serializers_(serializers) { +} + +MAMResultSerializer::~MAMResultSerializer() { +} + +std::string MAMResultSerializer::serializePayload(boost::shared_ptr<MAMResult> payload) const { +	if (!payload) { +		return ""; +	} + +	XMLElement element("result", "urn:xmpp:mam:0"); + +	element.setAttribute("id", payload->getID()); + +	if (payload->getQueryID()) { +		element.setAttribute("queryid", *payload->getQueryID()); +	} + +	element.addNode(boost::make_shared<XMLRawTextNode>(ForwardedSerializer(serializers_).serialize(payload->getPayload()))); + +	return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h new file mode 100644 index 0000000..bb0c326 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMResult.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { +	class PayloadSerializerCollection; + +	class SWIFTEN_API MAMResultSerializer : public GenericPayloadSerializer<MAMResult> { +		public: +			MAMResultSerializer(PayloadSerializerCollection* serializers); +			virtual ~MAMResultSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<MAMResult>) const SWIFTEN_OVERRIDE; + +		private: +			PayloadSerializerCollection* serializers_; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.cpp new file mode 100644 index 0000000..86d8830 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/lexical_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> + +using namespace Swift; + +ResultSetSerializer::ResultSetSerializer() { +} + +ResultSetSerializer::~ResultSetSerializer() { +} + +std::string ResultSetSerializer::serializePayload(boost::shared_ptr<ResultSet> payload) const { +	if (!payload) { +		return ""; +	} + +	XMLElement element("set", "http://jabber.org/protocol/rsm"); + +	if (payload->getMaxItems()) { +		element.addNode(boost::make_shared<XMLElement>("max", "", boost::lexical_cast<std::string>(*payload->getMaxItems()))); +	} + +	if (payload->getCount()) { +		element.addNode(boost::make_shared<XMLElement>("count", "", boost::lexical_cast<std::string>(*payload->getCount()))); +	} + +	if (payload->getFirstID()) { +		boost::shared_ptr<XMLElement> firstElement = boost::make_shared<XMLElement>("first", "", *payload->getFirstID()); +		if (payload->getFirstIDIndex()) { +			firstElement->setAttribute("index", boost::lexical_cast<std::string>(*payload->getFirstIDIndex())); +		} +		element.addNode(firstElement); +	} + +	if (payload->getLastID()) { +		element.addNode(boost::make_shared<XMLElement>("last", "", *payload->getLastID())); +	} + +	if (payload->getAfter()) { +		element.addNode(boost::make_shared<XMLElement>("after", "", *payload->getAfter())); +	} + +	return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h new file mode 100644 index 0000000..1d476e2 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ResultSet.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { +	class PayloadSerializerCollection; + +	class SWIFTEN_API ResultSetSerializer : public GenericPayloadSerializer<ResultSet> { +		public: +			ResultSetSerializer(); +			virtual ~ResultSetSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<ResultSet>) const SWIFTEN_OVERRIDE; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp new file mode 100644 index 0000000..8af1672 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +class ForwardedSerializerTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(ForwardedSerializerTest); +		CPPUNIT_TEST(testSerializeIQ); +		CPPUNIT_TEST(testSerializeMessage); +		CPPUNIT_TEST(testSerializeMessageNoDelay); +		CPPUNIT_TEST(testSerializePresence); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testSerializeIQ() { +			ForwardedSerializer serializer(&serializers); + +			boost::shared_ptr<IQ> iq = IQ::createResult(JID("juliet@capulet.lit/balcony"), JID("romeo@montague.lit/orchard"), "id0"); + +			boost::shared_ptr<Forwarded> forwarded(boost::make_shared<Forwarded>()); +			forwarded->setStanza(iq); +			forwarded->setDelay(boost::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + +			std::string expectedResult =  +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<delay stamp=\"2010-07-10T23:08:25Z\" xmlns=\"urn:xmpp:delay\"/>" +					"<iq from=\"romeo@montague.lit/orchard\" id=\"id0\" to=\"juliet@capulet.lit/balcony\" type=\"result\" xmlns=\"jabber:client\"/>" +				"</forwarded>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(forwarded)); +		} + +		void testSerializeMessage() { +			ForwardedSerializer serializer(&serializers); + +			boost::shared_ptr<Message> message(boost::make_shared<Message>()); +			message->setType(Message::Chat); +			message->setTo(JID("juliet@capulet.lit/balcony")); +			message->setFrom(JID("romeo@montague.lit/orchard")); +			message->setBody("Call me but love, and I'll be new baptized; Henceforth I never will be Romeo."); + +			boost::shared_ptr<Forwarded> forwarded(boost::make_shared<Forwarded>()); +			forwarded->setStanza(message); +			forwarded->setDelay(boost::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + +			std::string expectedResult =  +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<delay stamp=\"2010-07-10T23:08:25Z\" xmlns=\"urn:xmpp:delay\"/>" +					"<message from=\"romeo@montague.lit/orchard\" to=\"juliet@capulet.lit/balcony\" type=\"chat\" xmlns=\"jabber:client\">" +						"<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>" +					"</message>" +				"</forwarded>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(forwarded)); +		} + +		void testSerializeMessageNoDelay() { +			ForwardedSerializer serializer(&serializers); + +			boost::shared_ptr<Message> message(boost::make_shared<Message>()); +			message->setType(Message::Chat); +			message->setTo(JID("juliet@capulet.lit/balcony")); +			message->setFrom(JID("romeo@montague.lit/orchard")); +			message->setBody("Call me but love, and I'll be new baptized; Henceforth I never will be Romeo."); + +			boost::shared_ptr<Forwarded> forwarded(boost::make_shared<Forwarded>()); +			forwarded->setStanza(message); + +			std::string expectedResult =  +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<message from=\"romeo@montague.lit/orchard\" to=\"juliet@capulet.lit/balcony\" type=\"chat\" xmlns=\"jabber:client\">" +						"<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>" +					"</message>" +				"</forwarded>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(forwarded)); +		} + +		void testSerializePresence() { +			ForwardedSerializer serializer(&serializers); + +			boost::shared_ptr<Presence> presence(boost::make_shared<Presence>()); +			presence->setType(Presence::Subscribe); + +			boost::shared_ptr<Forwarded> forwarded(boost::make_shared<Forwarded>()); +			forwarded->setStanza(presence); +			forwarded->setDelay(boost::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + +			std::string expectedResult =  +				"<forwarded xmlns=\"urn:xmpp:forward:0\">" +					"<delay stamp=\"2010-07-10T23:08:25Z\" xmlns=\"urn:xmpp:delay\"/>" +					"<presence type=\"subscribe\" xmlns=\"jabber:client\"/>" +				"</forwarded>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(forwarded)); +		} + +	private: +		FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ForwardedSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MAMArchivedSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMArchivedSerializerTest.cpp new file mode 100644 index 0000000..b174d32 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMArchivedSerializerTest.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Serializer/PayloadSerializers/MAMArchivedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +class MAMArchivedSerializerTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(MAMArchivedSerializerTest); +		CPPUNIT_TEST(testSerialize); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testSerialize() { +			MAMArchivedSerializer serializer(&serializers); + +			boost::shared_ptr<MAMArchived> archived(boost::make_shared<MAMArchived>()); +			archived->setBy("juliet@capulet.lit"); +			archived->setID("28482-98726-73623"); + +			std::string expectedResult = +				"<archived by=\"juliet@capulet.lit\" id=\"28482-98726-73623\" xmlns=\"urn:xmpp:mam:0\"/>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(archived)); +		} + +	private: +		FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMArchivedSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp new file mode 100644 index 0000000..cc49be1 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/MAMResult.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +class MAMQuerySerializerTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(MAMQuerySerializerTest); +		CPPUNIT_TEST(testSerialize); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testSerialize() { +			MAMQuerySerializer serializer(&serializers); + +			boost::shared_ptr<Form> parameters(boost::make_shared<Form>()); + +			boost::shared_ptr<FormField> fieldType = boost::make_shared<FormField>(FormField::TextSingleType); +			fieldType->setName("FORM_TYPE"); +			fieldType->addValue("urn:xmpp:mam:0"); +			parameters->addField(fieldType); + +			boost::shared_ptr<FormField> fieldStart = boost::make_shared<FormField>(FormField::TextSingleType); +			fieldStart->setName("start"); +			fieldStart->addValue("2010-08-07T00:00:00Z"); +			parameters->addField(fieldStart); + +			boost::shared_ptr<ResultSet> set = boost::make_shared<ResultSet>(); +			set->setMaxItems(10); + +			boost::shared_ptr<MAMQuery> query(boost::make_shared<MAMQuery>()); +			query->setQueryID(std::string("id0")); +			query->setForm(parameters); +			query->setResultSet(set); + +			std::string expectedResult = +				"<query queryid=\"id0\" xmlns=\"urn:xmpp:mam:0\">" +					"<x type=\"form\" xmlns=\"jabber:x:data\">" +						"<field type=\"text-single\" var=\"FORM_TYPE\">" +							"<value>urn:xmpp:mam:0</value>" +						"</field>" +						"<field type=\"text-single\" var=\"start\">" +							"<value>2010-08-07T00:00:00Z</value>" +						"</field>" +					"</x>" +					"<set xmlns=\"http://jabber.org/protocol/rsm\">" +						"<max>10</max>" +					"</set>" +				"</query>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(query)); +		} + +	private: +		FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMQuerySerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp new file mode 100644 index 0000000..2060c97 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/MAMResult.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +class MAMResultSerializerTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(MAMResultSerializerTest); +		CPPUNIT_TEST(testSerialize); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testSerialize() { +			MAMResultSerializer serializer(&serializers); + +			boost::shared_ptr<Message> message(boost::make_shared<Message>()); +			message->setType(Message::Chat); +			message->setTo(JID("juliet@capulet.lit/balcony")); +			message->setFrom(JID("romeo@montague.lit/orchard")); +			message->setBody("Call me but love, and I'll be new baptized; Henceforth I never will be Romeo."); + +			boost::shared_ptr<Forwarded> forwarded(boost::make_shared<Forwarded>()); +			forwarded->setStanza(message); +			forwarded->setDelay(boost::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + +			boost::shared_ptr<MAMResult> result(boost::make_shared<MAMResult>()); +			result->setID("28482-98726-73623"); +			result->setQueryID(std::string("f27")); +			result->setPayload(forwarded); + +			std::string expectedResult =  +				"<result id=\"28482-98726-73623\" queryid=\"f27\" xmlns=\"urn:xmpp:mam:0\">" +					"<forwarded xmlns=\"urn:xmpp:forward:0\">" +						"<delay stamp=\"2010-07-10T23:08:25Z\" xmlns=\"urn:xmpp:delay\"/>" +						"<message from=\"romeo@montague.lit/orchard\" to=\"juliet@capulet.lit/balcony\" type=\"chat\" xmlns=\"jabber:client\">" +							"<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>" +						"</message>" +					"</forwarded>" +				"</result>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(result)); +		} + +	private: +		FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMResultSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp new file mode 100644 index 0000000..641b856 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Elements/ResultSet.h> + +using namespace Swift; + +class ResultSetSerializerTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(ResultSetSerializerTest); +		CPPUNIT_TEST(testSerializeFull); +		CPPUNIT_TEST(testSerializeMaxItems); +		CPPUNIT_TEST(testSerializeFirst); +		CPPUNIT_TEST(testSerializeFirstWithIndex); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void testSerializeFull() { +			ResultSetSerializer serializer; + +			boost::shared_ptr<ResultSet> resultSet(boost::make_shared<ResultSet>()); + +			resultSet->setMaxItems(100); +			resultSet->setCount(800); +			resultSet->setFirstIDIndex(123); +			resultSet->setFirstID(std::string("stpeter@jabber.org")); +			resultSet->setLastID(std::string("peterpan@neverland.lit")); +			resultSet->setAfter(std::string("09af3-cc343-b409f")); + +			std::string expectedResult =  +				"<set xmlns=\"http://jabber.org/protocol/rsm\">" +					"<max>100</max>" +					"<count>800</count>" +					"<first index=\"123\">stpeter@jabber.org</first>" +					"<last>peterpan@neverland.lit</last>" +					"<after>09af3-cc343-b409f</after>" +				"</set>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(resultSet)); +		} + +		void testSerializeMaxItems() { +			ResultSetSerializer serializer; + +			boost::shared_ptr<ResultSet> resultSet(boost::make_shared<ResultSet>()); + +			resultSet->setMaxItems(100); + +			std::string expectedResult =  +				"<set xmlns=\"http://jabber.org/protocol/rsm\">" +					"<max>100</max>" +				"</set>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(resultSet)); +		} + +		void testSerializeFirst() { +			ResultSetSerializer serializer; + +			boost::shared_ptr<ResultSet> resultSet(boost::make_shared<ResultSet>()); + +			resultSet->setFirstID(std::string("stpeter@jabber.org")); + +			std::string expectedResult =  +				"<set xmlns=\"http://jabber.org/protocol/rsm\">" +					"<first>stpeter@jabber.org</first>" +				"</set>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(resultSet)); +		} + +		void testSerializeFirstWithIndex() { +			ResultSetSerializer serializer; + +			boost::shared_ptr<ResultSet> resultSet(boost::make_shared<ResultSet>()); + +			resultSet->setFirstID(std::string("stpeter@jabber.org")); +			resultSet->setFirstIDIndex(123); + +			std::string expectedResult =  +				"<set xmlns=\"http://jabber.org/protocol/rsm\">" +					"<first index=\"123\">stpeter@jabber.org</first>" +				"</set>"; + +			CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(resultSet)); +		} +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ResultSetSerializerTest); diff --git a/Swiften/Serializer/StanzaSerializer.cpp b/Swiften/Serializer/StanzaSerializer.cpp index 9a4fd2c..b5f0b22 100644 --- a/Swiften/Serializer/StanzaSerializer.cpp +++ b/Swiften/Serializer/StanzaSerializer.cpp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2014 Remko Tronçon   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */ @@ -23,9 +23,13 @@ StanzaSerializer::StanzaSerializer(const std::string& tag, PayloadSerializerColl  }  SafeByteArray StanzaSerializer::serialize(boost::shared_ptr<Element> element) const { +	return serialize(element, ""); +} + +SafeByteArray StanzaSerializer::serialize(boost::shared_ptr<Element> element, const std::string& xmlns) const {  	boost::shared_ptr<Stanza> stanza(boost::dynamic_pointer_cast<Stanza>(element)); -	XMLElement stanzaElement(tag_); +	XMLElement stanzaElement(tag_, xmlns);  	if (stanza->getFrom().isValid()) {  		stanzaElement.setAttribute("from", stanza->getFrom());  	} diff --git a/Swiften/Serializer/StanzaSerializer.h b/Swiften/Serializer/StanzaSerializer.h index db18aa2..d569d82 100644 --- a/Swiften/Serializer/StanzaSerializer.h +++ b/Swiften/Serializer/StanzaSerializer.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2013-2014 Kevin Smith and Remko Tronçon   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */ @@ -18,7 +18,8 @@ namespace Swift {  		public:  			StanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers); -			virtual SafeByteArray serialize(boost::shared_ptr<Element>) const; +			virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; +			virtual SafeByteArray serialize(boost::shared_ptr<Element> element, const std::string& xmlns) const;  			virtual void setStanzaSpecificAttributes(boost::shared_ptr<Element>, XMLElement&) const = 0;  		private: | 
 Swift
 Swift